- 基类都有虚析构函数
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;
};
-
派生类不总是覆盖基类的虚函数
-
在一个对象中,继承自基类的部分和派生类自定义的部分不一定是连续存储的
-
Quote item; // 基类对象 Bulk_quote bulk; // 派生类对象 Quote *p = &item; // p指向基类Quote对象 p = &bulk; // p指向派生类bulk中的Quote部分 Quote &r = bulk; // r绑定到bulk的Quote部分
-
派生类可以访问基类的公有成员和受保护成员
-
静态成员只存在唯一的定义
-
成员函数可以在类内定义和生明,也可以在类内声明,类外定义
class Base { public: void f(const Base&); }; // 在类内声明成员函数, 类外定义 void Base::f(const Base& deli) { .....; };
-
一个派生类的函数如果覆盖了某个继承而来的虚函数,则它的形参类型必须与被它覆盖的基类函数完全一致;返回类型也必须匹配
-
可以把某个函数指定为final,则任何操作都不能覆盖该函数
void f(int) const final;
-
=0
声明一个纯虚函数;含有纯虚函数的类是抽象基类;不能创建抽象基类的对象 -
派生类的成员或友元,只能通过派生类对象来访问基类的受保护对象
-
友元关系不能传递,也不能继承
class Base { friend class Pal; // 声明友元类 protected: int prot_mem; };
-
使用using可以改变派生类的成员的访问级别
class Base { public: std::size_t size() const { return n; } protected: std::size_t n; }; class Pal : private Base // Pal私有继承自Base,则继承来的成员是Pal的私有成员,使用using改变成员的访问等级 { public: using Base::size; protected: using Base::n; };
-
默认情况下,使用class关键字定义的派生类是私有继承;使用struct关键字定义的派生类是公有继承
class Base{...}; class D1 : Base{...}; //私有继承 struct D2 : Base{...}; //公有继承
-
派生类的成员隐藏同名的基类成员
struct Base { Base() : mem(0){ } //用0初始化 mem protected: int mem; }; struct Derived : Base{ Derived(int i): mem(i){ } // 用i初始化 i int get_mem() {return mem;} // 可以使用作用域运算符来访问隐藏的基类成员 int get_base_mem() {return Base::mem;} protected: int mem; }
-
类对象在被创建时,就会调用构造函数;被销毁时调用析构函数
-
当一个继承自基类的对象被创建时,先调用基类的构造函数,在调用自己的构造函数,当该对象被销毁时,先调用自己的析构函数,再调用基类的析构函数
-
目的:让一个函数或者一个类,访问另一个类中的私有成员
-
class Student { // 在类内将 外部函数声明为该类的友元 friend void friend_Student(Student* s); public: int m_age; Student() { m_age = 20; m_name = "青春"; } private: std::string m_name; }; void friend_Student(Student* s) { std::cout <<"在类外访问公有成员"<< s->m_age << std::endl; std::cout <<"在类外访问私有成员"<< s->m_name << std::endl; } int main() { Student s; friend_Student(&s); return 0; }
-
当前行被执行完成后,立即释放
-
class Base { public: Base() { std::cout<<"hello"<<std::endl; } } Base(); // 创建一个匿名对象,当前行执行完后立即释放
- 父类的私有成员不管以什么方式继承都不可以访问
- 公有继承不改变父类中的访问权限
- 公有继承下类内可以访问父类的protected成员
- 保护继承下,父类的public成员在子类中变为protected,子类外部无法访问
- 保护权限类外不可以访问
- 如果子类中有跟父类同名的成员函数,则父类中与子类成员函数同名的成员函数会被隐藏
- 虚继承virtual可以解决菱形继承问题(虚继承)
- 允许父类与子类之间的转换,父类的引用或指针可以直接指向子类对象
- 当子类重写父类的虚函数,子类中的虚函数表内部,会替换成子类的虚函数地址,当父类的指针或者引用指向子类对象时,发生多态
- 纯虚函数语法:
virtual 返回值类型 函数名(参数列表)= 0;
- 当类中有了纯虚函数,这个类被称为抽象类
- 抽象类无法实例化对象
- 子类必须重写抽象类中的纯虚函数,否则也属于抽象类
- 使用多态时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码;解决该问题的方式是将父类的析构函数改为虚析构或者纯虚析构