C++入门7 类|构造函数|析构函数

一,类型设计和实例化对象

封装是面向对象程序设计最基本的特性, 把数据 (属性) 和函数 (操作) 合成一个整体,这在计算机世界中是用类与对象实现的。


C++中类的设计

1 class 类型名称
2 {
3 public:
4 成员列表1;
5 protected:
6 成员列表2;
7 private:
8 成员列表3;
9 };//最后的分号不可少;注意:所有说明都有分号


 其中“class 类名”称为类头。花括号中的部分称为类体, 类体中定义了类成员表 。

在C++中,类是一种数据类型。客观事物是复杂的,要描述它必须从多方面进行,也就是用不同的

数据类型来描述不同的方面。如商场中的商品可以这样描述:

 商品名称(用字符串描述),该商品数量(用整型数描述),该商品单价 (用浮点数描述),该商品总

价 (用浮点数描述)。

这里用了属于三种不同数据类型,四个数据成员(data member)来描述一种商品。

在C++中可以这样表述:
 

1 class CGoods
2 {
3 public:
4 char Name[21];//std::string Name;
5 int Amount;
6 float Price;
7 float Total _ value;
8 };


 关键字class 是数据类型说明符,指出下面说明的是类型。标识符CGoods是商品这个类的类型

名。花括号中是构成类体的一系列的成员,关键字 public 是一种访问限定符。
 

访问限定符有三种: public (公共的) , private (私有的) 和protected(保护的)。第

一种说明的成员能从外部进行访问,另外两种说明的成员不能从外部进行访问。每种说明符可在类

体中使用多次。它们的作用域是从该说明符出现开始到下一个说明符之前或类体结束之前结束。

 如果在类体起始点无访问说明符, 系统默认定义为私有。访问说明符private 和

protected 体现了类具有封装性 。

示例:

1 class CGoods
2 {
3 public:
4 char Name[21]; //std::string Name;
5 int Amount;
6 float Price;
7 float Total _ value;
8 };
9 int main()
10 {
11 Amount = 100; 
12 Price = 128.99;
13 return 0;
14 }

成员函数


类型设计的更关键部分是对数据成员的操作,用函数来完成:

1 class CGoods
2 {
3 private:
4 char Name[21]; //std::string Name;
5 int Amount;
6 float Price;
7 float Total _ value;
8 public:
9 void RegisterGoods(const char [], int, float); //注册
10 void CountTota1(); //计算商品总价值
11 void GetName(char name[]); //读取商品名
12 int GetAmount(); //读取商品数量
13 float GetPrice(); //读取商品单价
14 float GetTotal_ value(void); //读取商品总价值
15 };


这样在类中引进了成员函数或函数成员,也就是函数也成了数据(类)中的一员。类把数据(事物的属

性)和函数 (事物的行为--操作)封装为一个整体。

四个数据成员被说明成私有,而六个函数成员被说明成公有;这就是说如果从外部对四个数据成员

进行操作的话,只能通过六个公有函数来完成,数据受到了良好的保护,不易受外部环境的影响。

公有函数集定义了类的接口 。

类是一种数据类型,设计时系统不为类分配存储空间,所以不能对类的数据成员初始化。类中的任

何数据成员也不能使用关键字extern、auto或register限定其存储类型。

成员函数可以直接使用类定义中的任一成员,可以处理数据成员,也可调用函数成员。成员函数的

定义:

前面只对成员函数作了一个声明(函数的原型),并没有对函数进行定义。

函数定义通常在类的说明之后进行,其格式如下:

回值类型 类名::函数名(参数表)

{……}//函数体

其中运算符“::”称为作用域解析运算符(scope resolution operator), 它指出该函数是属于哪一个类的

成员函数。

商品类型的完整设计:

1 class CGoods
2 {
3 private:
4 char Name[21]; //std::string Name;
5 int Amount;
6 float Price;
7 float Tota1_ value;
8 public:
9 void RegisterGoods(const char [], int , float ); //注册
10 void CountTota1(void); //计算商品总价值
11 void GetName(char name[]); //读取商品名
12 int GetAmount(void); //读取商品数量
13 float GetPrice(void); //读取商品单价
14 float GetTota1_ value(void) //读取商品总价值
15 {
16 return Total _ value;
17 }
18 };
19 void CGoods::RegisterGoods(const char name[], int amount, float price)
20 (
21 Name = name ;
22 Amount = amount;
23 Price = price;
24 }
25 void CGoods::CountTota1(void)
26
27 Total _ value = Price * Amount;
28 }
29 void CGoods::GetName(char name[])
30
31 strcpy(name, Name);
1
32
33 int CGoods::GetAmount(void) { return (Amount); }
34 float CGoods::GetPrice(void) { return (Price); }
35 //float cGoods::GetTota1_ value(void) { return(Total _ value); }


对象的创建与使用


对象是类的实例。声明一种数据类型只是告诉编译系统该数据类型的构造,并没有预定内存。类只

是一个样板,以此样板可以在内存中开辟出同样结构的实例--对象。

创建类的对象可以有两种常用方法。

第一种是直接定义类的实例--对象:

1 int a;
2
3 CGoods Car;


这个定义创建了CGoods类的一个对象Car,同时为它分配了属于它自己的存储块,用来存放数据

和对这些数据实施操作的成员函数 。对象只在定义它的域中有效。

对象的使用:

1 int main()
2 {
3 CGoods tea;
4 CGoods book;
5 tea. RegisterGoods("black _ tea", 12, 560);
6 tea. CountTota1();
7 book. RegisterGoods("Thinking In C++", 20, 128);
8 book. CountTota1();
9 return 0;
10 }


对象使用的规则很简单,只要在对象名后加点号,再加成员数据或成员函数名就可以了。但是这些

成员必须是公有的成员,只有公有成员才能在对象的外面对它进行访问。

this指针的作用


编译器针对程序员自己设计的类型分三次编译。


第一:识别和记录类体中属性的名称,类型和访问限定,与属性在类体中的位置无关。
如 class CGoods 中的Name, Amount, Price, Total _ value;

第二:识别和记录类体中函数原型(返回类型+函数名+参数列表),形参的默认值,访问限定。不识别函数体。

第三:改写在类中定义函数的参数列表和函数体,改写对象调用成员函数的形式;

示例:

1 class CGoods
2 {
3 private:
4 char Name[21];
5 int Amount;
6 float Price;
7 float Total _ value;
8 public:
9 void RegisterGoods(const char *name, int, float);
10 void CountTota1();
11 };
12 void CGoods::RegisterGoods(const char *name, int amount, float price)
13 {
14 strcpy(Name, name); //字符串拷贝函数
15 Amount = amount;
16 Price = price;
17 }
18 void CGoods::CountTota1()
19 {
20 Total _ value = Price * Amount;
21 }
22 int main()
23 {
24 CGoods tea;
25 CGoods book;
26 tea. RegisterGoods("black _ tea", 12, 560);
27 tea. CountTota1();
28 book. RegisterGoods("Thinking In C++", 20, 128);
29 book. CountTota1();
30 return 0;
31 }

改写后的代码:

1 class CGoods
2 {
3 private:
4 char Name[21];
5 int Amount;
6 float Price;
7 float Total _ value;
8 public:
9 //void RegisterGoods(CGoods * const this, const char *name, int, float);
10 void RegisterGoods(const char *name, int, float);
11 //void CountTota1(CGoods * const this);
12 void CountTota1();
13 };
14 //void CGoods::RegisterGoods(CGoods* const this, const char *name, int amount, float price);
15 void CGoods::RegisterGoods(const char *name, int amount, float price)
16 {
17 strcpy(this->Name, name);
18 this->Amount = amount;
19 this->Price = price;
20 }
21 // void CGoods::CountTotal(CGoods * const this);
22 void CGoods::CountTota1()
23 {
24 this->Total _ value = this->Price * this->Amount;
25 )
26 int main()
27 {
28 CGoods tea;
29 CGoods book;
30 tea. RegisterGoods("black _ tea", 12, 560);
31 // RegisterGoods(&tea,"black _ tea",12,560);
32 tea. CountTota1();
33 // CountTota1(&tea);
34 book. RegisterGoods("Thinking In C++", 20, 128);
35 // RegisterGoods(&book,"Thinking In C++",20,128);
36 book. CountTota1();
37 // CountTotal(&book);
38 return 0;
39 }

全局函数和成员函数的区别


重点是this指针:
其间的差别在于一个是程序的需要,一个是编译器的需要。
程序如果有需要,那是程序员的责任;


二,构造函数与析构函数


数据成员多为私有的,要对它们进行初始化,必须用一个公有函数来进行。同时这个函数应该在且

仅在定义对象时自动执行一次。称为构造函数 (constructor) 。

构造函数用途:1)创建对象,2)初始化对象中的属性,3)类型转换。

构造函数的定义与使用


构造函数是特殊的公有成员函数 ,其特征如下:
1.函数名与类名相同。


2.构造函数无函数返回类型说明。注意是没有而不是void,即什么也不写,也不可写void。实际上构造函数有返回值,返回的就是构造函数所创建的对象。


3.在程序运行时,当新的对象被建立,该对象所属的类构造函数自动被调用,在该对象生存期中也只调用这一次。


4.构造函数可以重载。严格地讲,类中可以定义多个构造函数,它们由不同的参数表区分,系统在自动调用时按一般函数重载的规则选一个执行。


5.构造函数可以在类中定义,也可以在类中声明,在类外定义。


6.如果类说明中没有给出构造函数,则C++编译器自动给出一个缺省的构造函数:
类名(void){ }
但只要我们定义了一个构造函数,系统就不会自动生成缺省的构造函数。只要构造函数是无参的或者只要各参数均有缺省值的,C++编译器都认为是缺省的构造函数,并且缺省的构造函数只能有一个

1 class Complex
2 {
3 int Real; //实部
4 int Image; //虚部
5 public:
6 Complex() //缺省的构造函数
7 {
8 Real = 0.0;
9 Image = 0.0;
10 cout<<"Create object: Complex()"<<end1;
11 }
12 Complex(int r, int i) // 带参数的构造函数
13 {
14 Real = r;
15 Image = i;
16 cout<<"Create object: Complex(int , int ) "<<end1;
17 }
18 void Print()
19 {
20 cout<<"Real = "<<real<<' t'<<" Image = "<<image<<end1;
21 }
22 };
23
24 int main()
25 {
26 Complex ca;
27 Complex cb(1,2);
28 Complex cc = Complex(3,4);
29 Complex cd{5,6};
30 Comple x ce(); // 是否可以构造对象;
31 return 0;
32 }

成员初始化表

1 class Comp1ex
2 {
3 int real; //实部
4 int image; //虚部
5 public:
6 Complex():real{}, image{} //缺省的构造函数
7 {
8 cout<<"Create Object: Complex()"<<end1;
9 }
10 //Complex(int r, int i) :Real(r), Image(i)
11 Complex(int r, int i) :Real{r}, Image{i}// 带参数的构造函数
12 {
13 // Real = r;
14 // Image = i;
15 cout<<"Create object: Complex(int, int) "<<end1;
16 }
17 void Print() const // 常方法
18 {
19 cout<<"real = "<<rea1<<" \t<<" image = "<<image<<end1;
20 }
21 };
22
23 int main()
24 {
25 Complex ca;
26 Complex cb(1,2);
27 Complex cc = Complex(3,4);
28 Complex cd{5,6};
29 Comple x ce(); // 是否可以构造对象;
30 return 0;
31 }

析构函数


析构函数的定义当定义一个对象时,C++自动调用构造函数建立该对象并进行初始化,那么当一个对象的生命周期结束时,C++也会自动调用一个函数注销该对象并进行善后工作,这个特殊的成员函数即析构函数 :


1.构函数名与类名相同,但在前面加上字符'~',如:~CGoods ()。


2.析构函数无函数返回类型,与构造函数在这方面是一样的。但析构函数不带任何参数。
3.一个类有一个也只有一个析构函数,这与构造函数不同。


4.对象注销时,系统自动调用析构函数。


5.如果类说明中没有给出析构函数,则C++编译器自动给出一个缺省的析构函数。


如:~类型名称(){}

1 class Complex
2 {
3 double Rea1; //实部
4 double Image; //虚部
5 public:
6 Complex():Real{}, Image{} //缺省的构造函数
7 {
8 cout<<"Create object: "<<this<<end1;
9 }
10 Complex(double r, double i):Rea1{r}, Image{i}// 带参数的构造函数
11 {
12 cout<<"Create object: "<<this<<end1;
13 }
14 ~Comp1ex()
15 {
16 cout<<"Destroy object: "<<this<<end1;
17 }
18 void Print() const // 常方法
19 {
20 cout<<"Rea1 = "<<Rea1<<' t'<<" Image = "<<Image<<end1;
21 }
22 };

相关推荐

  1. C++入门7 |构造函数|函数

    2024-06-10 23:58:02       7 阅读
  2. C++入门【36-C++ 构造函数 & 函数

    2024-06-10 23:58:02       31 阅读
  3. C++ 构造函数 & 函数

    2024-06-10 23:58:02       40 阅读
  4. C++ 构造函数 & 函数

    2024-06-10 23:58:02       19 阅读
  5. C++ 函数构造函数

    2024-06-10 23:58:02       38 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-10 23:58:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-10 23:58:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-10 23:58:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-10 23:58:02       20 阅读

热门阅读

  1. linux Ubuntu安装samba服务器与SSH远程登录

    2024-06-10 23:58:02       11 阅读
  2. MC服务器怎么搭建

    2024-06-10 23:58:02       10 阅读
  3. TypeScript (TS) 类型定义总结

    2024-06-10 23:58:02       9 阅读
  4. spring 事务隔离级别

    2024-06-10 23:58:02       11 阅读
  5. 实验3-单链表(优化版/王道版)

    2024-06-10 23:58:02       9 阅读
  6. 数据结构-哈希表

    2024-06-10 23:58:02       10 阅读
  7. Qt定时器

    2024-06-10 23:58:02       9 阅读
  8. 【第一篇】SpringSecurity的入门

    2024-06-10 23:58:02       11 阅读
  9. 【手撕面试题】Vue(高频知识点五)

    2024-06-10 23:58:02       9 阅读