class Quote {
public:
Quote(int x) :x(x) {}
//如果我们删除的是一个指向派生类对象的基类指针,则需要虚析构函数
virtual ~Quote() = default;//动态绑定析构函数
int x;
virtual void show()
{
cout << x << endl;
}
};
class Bulk_quote :public Quote
{
public:
Bulk_quote(int x,int y) :Quote(x), y(y) {}
int y;
void show()
{
cout << y << endl;
}
};
int main()
{
构造函数与拷贝控制
//继承体系中的类和其他的类一样,也会有创建、拷贝、移动、赋值和销毁,没有定义时编译器也会合成一个版本,合成的版本也定义为删除的。
虚析构函数
//继承关系对基类拷贝控制最直接的影响是基类通常应该定义一个虚析构函数,这样就能动态分配继承体系中的对象了。
//虚析构函数也会被继承,delete基类指针时将运行真确的析构函数版本。
//如果基类的析构函数不是虚函数,则delete一个指向派生类对象的基类指针将产生未定义的行为。
//虚析构函数将阻止合成移动操作。
Quote* itemP = new Quote(9);//静态类型与动态类型一致
delete itemP;//调用Quote的析构函数
itemP = new Bulk_quote(9,8);//静态类型与动态类型不一致
delete itemP;//调用Bulk_quote的析构函数
合成拷贝控制与继承
//除了对类本身的成员依次进行初始化、赋值或销毁的操作外,合成的成员还负责使用直接基类中对应的操作对一个对象直接基类部分进行相应的操作。
//基类中定义的拷贝控制函数是被删除的活不可访问的,则派生类中对应的成员将是被删除的。
//如果在基类中有一个不可访问或被删除的析构函数,则派生类中合成的默认和拷贝构造函数将是被删除的,因为编译器无法销毁派生类对象的基类部分。
//编译器不会合成一个删除的移动操作。
class B
{
public:
B();
B(const B&) = delete;
};
class D :public B{};
D d;//正确 D会合成默认构造函数使用B的默认构造函数
D d2(d);//错误 D的合成拷贝构造函数是被删除的
D d3(std::move(d));//错误 隐式地使用D的被删除的拷贝构造函数
移动操作与继承
//默认情况下,基类通常不含有合成的移动操作,而且在它的派生类中也没有合成的移动操作。
//因为基类缺少移动操作会阻止派生类拥有自己的合成移动操作,所以当我们需要执行移动操作时,应该首先在基类中进行定义。
//除非派生类含有排斥移动的成员,否则将自动获得合成的移动操作。
class Quote
{
public:
Quote() = default;//对成员依次进行默认初始化
Quote(const Quote&) = default;//队成员依次拷贝
Quote(Quote&&) = default;//队成员依次拷贝
Quote& operator=(const Quote&) = default;//拷贝赋值
Quote& operator=(Quote&&) = default;//移动赋值
virtual ~Quote() = default;
};
派生类的拷贝控制成员
//当派生类定义了拷贝或移动操作时,该操作负责拷贝或移动包括基类部分成员在内的整个对象。
class Base{};
class D :public Base
{
public:
//默认情况下,基类的默认构造函数初始化对象的基类部分
//要想使用拷贝或移动构造函数,必须在构造函数初始值列表中显示地调用该构造函数
D(const D& d) :Base(d) /*派生类成员赋值*/
{}
D(D&& d):Base(std::move(d)){}
//派生类赋值运算符
//派生类的赋值运算符也要显示的为基类部分赋值
D& operator=(const D& rhs)
{
Base::operator=(rhs);//为基类部分赋值
/*为派生类成员赋值*/
return *this;
}
//析构函数只负责销毁派生类自己分配的资源,基类部分会隐式的自动销毁。
//也就是析构函数只负责自己成员的销毁。
~D();
};
//如果构造函数或析构函数调用了某个虚函数,则我们应该执行与构造函数或析构函数所属类型相对应的虚函数版本。
继承的构造函数
//一个类只能继承其直接基类的构造函数。类不能继承默认、拷贝和移动构造函数。
//派生类继承基类构造函数的方式是提供一条注明基类名的using声明语句。
class D :public Base
{
public:
//当作用于构造函数时,using声明语句将令编译器产生代码,不会改变该构造函数的访问级别。
//using声明语句不能指定explicit或constexpr。
using Base::Base;//继承Base的构造函数
};
容器与继承
//容器和存在继承关系的类型无法兼容
//在容器中放置指针或智能指针而非对象
vector<shared_ptr<Quote>> bask;
bask.push_back(make_shared<Quote>(10));
bask.push_back(make_shared<Bulk_quote>(6,7));
bask.back()->show();
return 0;
}