C++Primer-定义基类和派生类
定义基类
class Quote { public: Quote() = default; Quote(const std::string &book, double sales_price):bookNo(book), price(sales_price){} std::string isbn() const {return bookNo;} virtual double net_price(std::size_t n) const {return n * price;} virtual ~Quote() = default; private: std::string bookNo; protected: double price = 0.0; };
基类通常都需要定义一个虚析构函数,即使此函数不执行任何操作
成员函数与继承
派生类可以继承基类的成员,然而当遇到与类型相关的操作时,派生类必须重新定义,也就是提供自己的新定义从而覆盖继承的旧定义
基类的成员函数分为两种,一种是希望派生类直接继承的函数(通过定义虚函数),一种是希望派生类进行新定义覆盖的函数。当使用指针或者引用调用虚函数时,该调用将被动态绑定
任何构造函数之外的非静态函数都可以是虚函数,virtual只能用于类内声明而不能用于类外定义
访问控制和继承
派生类可以继承基类的成员,但是不一定能访问,派生类只能访问公有的和被保护的部分
定义派生类
派生类要使用类派生列表注明从哪些类继承,以及访问权限,需要覆盖的要重新声明
class Bulk_Quote : public Quote { public: Bulk_quote() = default; Bulk_quote(const std::string&, double, std::size_t, double); double net_price(std::size_t) const override; private: std::size_t min_qty = 0; double discount = 0.0; };
派生类构造函数
派生类不能直接初始化基类的成员,必须使用基类的构造函数来初始化它的基类部分。派生类的构造函数通过初始化列表,把参数传给基类构造函数进行构造
继承与静态成员
基类定义的静态成员会成为整个继承体系的唯一定义
防止继承的发生
类名后面加final
静态类型和动态类型
静态类型在编译时是已知的,动态类型要到运行时才可知,静态类型是声明或表达式生成的类型,动态类型是变量或表达式表示的内存中的对象类型。若表达式不是指针或引用,则动态类型会与静态类型一致
类型转换
编译器存在隐式的派生类向基类的类型转换,不存在基类到派生类的类型转换
编译器的隐式类型转换只对指针和引用生效,对象之间不能直接转换,但是可以将派生类对象拷贝、移动或赋值给基类对象,这种情况下,派生类中除基类以外的部分将被切掉