c++基础知识(8)
c++ primer plus第十章知识,包括抽象和类、构造函数和析构函数、this
指针、对象数组和类作用域。
抽象和类
c++中的类
类规范由两个部分组成
- 类声明:以数据成员的方式描述数据部分,以成员函数(被称为方法)的方式描述公有接口
- 类方法定义:描述如何实现类成员函数
通常,c++程序员将接口(类定义)放在头文件中,并将实现(类方法的代码)放在源代码文件中。
1 |
|
1 |
|
关键字private
和public
描述了对类成员的访问控制。使用类对象的程序都可以直接访问公有部分,但只能通过公有成员函数(或友元函数)来访问对象的私有成员。因此,公有成员函数时程序和对象的私有成员之间的桥梁,提供了对象和程序之间的接口。防止程序直接访问数据被称为数据隐藏,c++中还提供了第三个访问控制关键字protected
。
通常将数据项放在私有部 分,组成类接口的成员函数放在公有部分
类对象的默认访问控制是
private
类和结构的区别是,**结构体的默认访问类型是
public
**,而类为private
实现类成员函数
成员函数有函数头和函数体,也可以有返回类型和参数,除此之外还有两个特殊的特征:
- 定义成员函数时,使用作用域解析运算符
::
来标识函数所属的类 - 类方法可以访问类的
private
组件
例如,实现Stock类的update()成员函数
1 |
|
使用类
1 |
|
类的构造函数和析构函数
构造函数
每次创建类对象,c++都使用类构造函数
类的构造函数:专门用于构建新对象、将值赋给它们的数据成员。
构造函数和类的名称相同,并且没有返回值,没有被声明为void
类型。
1 |
|
使用构造函数
1 |
|
默认构造函数
默认构造函数是在未提供显示初始值时,用来创建对象的构造函数。
如果没有提供任何构造函数,则c++将自动提供默认构造函数。它是默认构造函数的隐式版本,不做任何工作。
当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数。
如果程序员定义了构造函数,但是未定义默认构造函数,当想使用默认构造函数时,就会报错
1
Stock stock1;//这样声明会出错
如何定义默认构造函数?
第一种方法:给已有的构造函数的所有参数提供默认值
1
Stock(const std::string &co = "Error", long n = 0, double pr = 0.0);
第二种方法:通过函数重载来定义另外一个构造函数——一个没有参数的构造函数
析构函数
用构造函数创建对象后,程序负责跟踪该对象,直到其过期为止。对象过期时,程序将自动调用一个特殊的成员函数——析构函数,该函数将完成清理工作。
析构函数:在类名前加上~
,例如,Stock类的析构函数为~Stock()
。析构函数与构造函数一样可以没有返回值和声明类型,除此之外,析构函数没有参数。
什么时候应该调用析构函数?
由编译器决定,通常不应在代码中显式地调用析构函数。 如果创建的是静态存储类对象,则其析构函数将在程序结束时自动调用。如果创建的是自动存储类对象,则其析构函数将在程序执行完代码块时自动被调用。如果对象是通过new创建的,则它将驻留在栈内存或自动存储区中,当使用delete来释放内存时,其析构函数将自动被调用。
在类对象过期时析构函数自动被调用,因此必须有一个析构函数。如果程序员没有提供析构函数,编译器将隐式地声明一个默认析构函数,并在发现导致对象被删除的代码后,提供默认析构函数的定义。
this 指针
当类的成员函数涉及到两个对象时,需要使用c++的this指针
假设现有类Stock
1 |
|
现有需求,找到两个Stock对象中total_val更大的那个对象,于是定义一个类成员函数
1 |
|
this
指针指向用来调用成员函数的对象,this
是对象的地址,*this
是对象本身。
函数调用stock1.topval(stock2)将this设置为stock1对象的地址;函数调用stock2.topval(stock1)将this设置为stock2对象的地址
对象数组
声明对象数组的方法和声明标准数据类型数组相同
1 |
|
可以用构造函数来初始化数组元素。在这种情况下,必须为每一个元素调用构造函数
1 |
|
类作用域
在函数中定义的名称(如类数据成员名和类成员函数名)的作用域都为整个类,作用域为整个类的名称只在该类中是已知的,在类外是不可知的。
类作用域意味着不能从外部直接访问类的成员,公有成员函数也是如此,即要调用公有成员函数,必须通过对象。
作用域为类的常量
有时,使符号常量的作用域为类很有用。例如类声明可能使字面值30来指定数组的长度。你可能会认为以下这样是可行的
1 |
|
这样子是行不通的,因为类声明只是描述对象的形式,并没有创建对象。因此在创建对象之前,将没有用于存储值的空间。
有两种方式可以实现这个目标,且效果相同
在类中声明一个枚举
1
2
3
4
5
6class Bakery
{
private:
enum {Months = 12};
double costs[Months];
}用这种方式声明枚举并不会创建类数据成员,也就是说所有对象中都不包含枚举。
使用关键字
static
1
2
3
4
5
6class Bakery
{
private:
static const int Months = 12;
double costs[Months];
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!