class Foo{
public:
Foo& operator=(const Foo &);
// . . .
}
析构函数释放对象使用的资源并销毁对象的非static成员
- 析构函数无返回值,也不接受参数
- 析构函数有一个函数体和一个析构部分,先执行函数体再销毁成员
- 在析构函数中不需要控制如何销毁,析构部分为隐式的。成员销毁依赖于成员类型
隐式销毁内置指针类型的成员不会delete它所指向的对象
class Foo{
public:
~Foo();
}
当一个类未定义自己的析构函数时,编译器会定义一个函数体为空的合成析构函数
析构函数体本身不直接销毁成员。成员是在函数体之后隐含的析构阶段中被销毁的。
三个基本操作控制类的拷贝操作:拷贝构造函数
、拷贝赋值运算符
、和析构函数
如果一个类需要自定义析构函数时,几乎可以肯定它也需要自定义拷贝赋值运算符和拷贝构造函数
如果一个类需要拷贝构造函数则一定需要拷贝赋值运算符
将拷贝控制成员定义为=default来显式要求编译器生成合成的版本
class Sales_data{
public:
Sales_data() = default; //显式要求合成默认构造函数
Sales_data(const Sales_data &) = default;
Sales_data & operator=(const Sales_data &);
~Sales_data();
};
Sales_data& Sales_data::operator = (const Sales_data) =default;
有些类需要组织拷贝与赋值,如iostream
类。使用=delete
将拷贝构造函数和拷贝赋值运算符定义为删除的函数。从而组织类对象的拷贝与赋值操作。
struct noCopy{
noCopy() =default;
noCopy() =(const noCopy &) =delete; //删除拷贝构造函数,阻止拷贝
noCopy & operator = (const niCopy&) =delete; //阻止赋值
~noCopy() =default;
//其他成员
};
类的每个对象都有单独的拷贝。对于有指针成员的类:
- 定义一个拷贝构造函数,完成
string
的拷贝,而不是拷贝指针 - 定义一个析构函数来释放
string
- 定义拷贝赋值运算符来释放当前对象的
string
,并从右侧运算对象拷贝string
类的每一个对象拷贝指针成员本身而不是它指向string,但析构函数不能单方面地释放关联的string。只有最后一个指向string的对象销毁时,才可以释放string。
实现类类似指针行为的方法是可以使用shared_ptr
智能指针。还可以使用引用计数
有些情况下对象被拷贝后就立即被销毁,这种情况下移动对象而非拷贝对象会大幅体升性能。
必须绑定到右值的引用,通过&&而不是&来获得右值引用
当运算符作用于类类型对象时,可以通过运算符重载重新定义该运算符的含义。
面向对象程序设计基于三个基本概念:数据抽象、继承、动态绑定。
面向对象程序设计(object-oriented)的核心思想:
数据抽象——将类的接口与实现分离;
继承——可以定义相似的类型并对其相似关系建模;
动态绑定——在一定程度上忽略相似类型的区别而以统一的方式使用它们的对象
类派生列表指明从哪个基类继承而来:
class Quote{
public:
std::string isbn() const;
virtual doouble net_price(std::size_t n) const;
};
//有类派生列表指明继承的基类
class Bilk_quote:public Quote{ //Quote 公有继承了 Bilk_quote
public:
double net_price(std::size_t) const override;
}
派生类显示注明使用某个成员函数覆盖其继承的虚函数使用override
关键字
在一个对象中,继承自基类的部分和派生类自定义的部分不一定是连续存储。