首页 > 编程语言 >C++入门7 类|构造函数|析构函数

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

时间:2024-06-09 13:04:14浏览次数:20  
标签:函数 int void float C++ 析构 CGoods 构造函数

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

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


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 };

标签:函数,int,void,float,C++,析构,CGoods,构造函数
From: https://blog.csdn.net/2303_76580416/article/details/139560421

相关文章

  • 【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化
    目录一、嵌入式系统简介二、C++在嵌入式系统中的优势三、机器学习在嵌入式系统中的挑战四、C++实现机器学习模型的基本步骤五、实例分析:使用C++在嵌入式系统中实现手写数字识别1.数据准备2.模型训练与压缩3.模型部署六、优化与分析1.模型优化模型量化模型剪枝......
  • 【调整堆】(C++ 代码实现 & 注释详解)
     自定义结构体:#definesz105typedefstructnode{ intlength; intl[sz];}SqList; 调整堆的函数:HeapAdjust函数思路说明://目标:将以s为根的子树调整为大根堆//具体操作:将路径上比s大的都往上移动,s往下移动,直到遇到比s还小的,就“放下”svoidHeapAdjust(SqList......
  • 跨语言系统中的功能通信:Rust、Java、Go和C++的最佳实践
    在现代软件开发中,使用多种编程语言构建复杂系统已成为一种常见的做法。每种编程语言都有其独特的优势和适用场景,这使得在同一个系统中使用多种语言变得合理且高效。然而,这也带来了一个重要的挑战:如何在这些不同语言之间实现高效、可靠的功能通信。本文将探讨Rust、Java、Go和C+......
  • 程序的基本结构、cout语句(c++语言)
    一、如何下载Dev C++    登录网站:ht.51goc.com二、安装DevC++一、启动DevC++   双击桌面的图标 二、新建一个程序三、复制一个程序    请你复制以下代码到“程序编辑区”    #include<bits/stdc++.h>usingn......
  • 【C++】初识C++
    【C++】初识C++文章概括关键字(C++98)命名空间命名空间的定义命名空间的特性输入与输出C++中的输入输出输入输出的命名空间缺省参数函数重载引用引用的概念引用的特性引用地使用场景引用做参数引用做返回值常引用常引用的俩个例子引用与指针的区别内联函数文章概括......
  • 【C++】类和对象(上)
    类和对象初步认识面向过程与对象类的引入类的定义类的封装类的访问限定符类的作用域类的实例化类的大小this指针this指针的特性初步认识面向过程与对象在之前初步学习C语言后,可以了解到C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题......
  • 避免内存泄漏:C++ 虚析构函数指南
    C++虚析构函数详解及示例在C++编程中,虚析构函数的使用至关重要,尤其在涉及多态时。以下将解释虚析构函数的作用、在基类中使用虚析构函数的必要性以及纯虚析构函数的定义。1.为什么需要虚析构函数?当基类的析构函数没有被声明为虚函数时,通过基类指针删除派生类对象会导致无......
  • C++ 抽象类与纯虚函数详解:理论与实战
    抽象基类为什么不能创建对象?抽象类是一种特殊的类,它被设计用来作为其他类的基类,不能实例化为对象。以下是关于抽象类和纯虚函数的详细解释:1.抽象类的定义:抽象类:带有纯虚函数的类称为抽象类。抽象类不能实例化对象,只能作为基类被继承。纯虚函数:一种没有实现的虚函数,其定义格......
  • 深入解析C++中自动生成默认构造函数的五种情况
    自动生成默认构造函数的情况以及相关解释在C++中,当一个类没有任何用户定义的构造函数时,编译器会自动为这个类生成一个默认构造函数。以下是具体情况的解释以及示例:1.带有默认构造函数的类成员对象如果一个类没有任何构造函数,但它含有一个成员对象,而该成员对象有默认构造......
  • 为什么C++友元函数必须在类内部声明?解析与案例
    友元函数是C++中独特的编程结构,允许一个非成员函数或者其他类访问另一个类的私有和保护数据成员。友元在很多情况下是非常有用的,比如操作符重载、类间紧密合作等。为什么需要在类内部声明友元函数?访问权限:友元函数需要访问类的私有和保护数据成员。为此,必须在类内部声明,以便......