浅谈C++中的类
类的基本思想
- 数据抽象
- 封装
- 接口
- 实现
类的性质
构造
当一个对象被创造出来,就称之为构造.构造的过程实际上是调用了类定义的构造函数
构造函数不能被声明为const
直接初始化构造
这种构造方式调用了初始化构造函数,用参数列表中的参数生成了一个对象
此构造函数可以被重载,有多个,实际调用参数列表最匹配的那个构造函数
|
|
这里是直接初始化,我们实际上是调用了string
类的初始化函数,参数是"init"
,生成了一个对象
拷贝构造
拷贝初始化
利用一个已有的对象初始化另一个对象,称为拷贝初始化
拷贝构造如果需要的话还会进行类型转换,所以一般其不应该为explicit
|
|
拷贝构造函数的型参应该为引用类型,因为为了调用拷贝构造函数,我们必须拷贝他的实参,然后我们又将调用拷贝构造函数,形成死循环
|
|
这里是拷贝初始化,我们实际上调用了拷贝构造函数,来生成了一个对象
拷贝赋值运算符
一个已初始化的对象,进行赋值操作时,实际上调用的就是复制运算符
它实际上执行了拷贝构造函数和析构函数的工作
|
|
阻止拷贝
我们可以在参数列表后加上=delete
,表示我们禁止拷贝操作
例如iostream
阻止了拷贝,避免多个对象写入或读取相同的IO
缓冲
移动构造
Copy can be expensive. --Bjarne Stroustrup
在重新分配内存时,将旧内存拷贝进新元素是不划算的,尤其是旧元素在此之后将不再被使用时
一个更好的办法是移动元素,将资源直接转交给新对象
|
|
移动赋值运算符
移动赋值运算符实际上执行了移动构造函数和析构函数的工作
右值引用
指必须绑定到右值的引用
它只能绑定到即将被销毁的对象上
右值一般是字面量,或求值过程中临时创建的对象
我们可以显式地将一个左值转换为右值std::move()
,于是便可以将右值引用绑定在上面
析构
当一个对象被销毁时,就会自动调用它自身定义的析构函数
总结
以上为类的基本属性,每当使用了一个属性本质上就是调用了相关的函数或方法
编译器的合成行为
如果我们需要编译器生成默认的行为,我们可以在参数列表后架上=default
显式地要求生成合成的方法
合成的拷贝构造函数
如果我们没有定义拷贝构造函数,那么编译器会自动生成一个
它实际上是将对象的成员逐一拷贝给另一个对象
- 如果成员为另一个类,就调用他本身的拷贝构造函数
- 如果类的成员为内置类型,就直接拷贝
- 如果成员为数组,就逐元素拷贝成员
合成的移动操作
当我们没有定义拷贝构造函数时,且成员均是可移动时,编译器将自动生成
当我们定义了拷贝构造函数,且无自定义移动行为时,编译器将会把移动操作定义为删除的函数
当我们未拷贝构造函数,且成员不可移动,编译器将会把移动操作定义为删除的函数
访问控制
public
在整个程序中都能被访问,为接口
private
只可以被类的成员函数访问
protexted
自身和其派生类有权访问
友元
类可以允许其他类或函数访问他的非公有成员,声明了友元即可
类的静态成员
声明
|
|
初始化
通常情况下,我们不应该在类的内部初始化类的静态成员
不过我们可以为静态成员提供const
整数类型的类内初始值,且要求静态成员必须为constepxr
|
|
性质
静态类的成员不与任何对象绑定在一起,也不能被声明为const
访问
|
|