一。赋值兼容性原则
1.子类对象可以当作父类对象使用
2.子类对象可以直接赋值给父类对象
3.子类对象可以直接初始化父类对象
4.父类指针可以直接指向子类对象
5.父类引用可以直接引用子类对象
#include <cstdlib> #include <iostream> using namespace std; class Parent { protected: char* name; public: Parent() { name = "Parent"; } void Print() { cout << "Name: " << name << endl; } }; class Child : public Parent { protected: int i; public: Child(int i) { this->i = i; this->name = "Child"; } }; int main(int argc, char *argv[]) { Child child(100); Parent parent = child; //初始化 Parent* pp = &child; //指针 Parent& rp = child; //引用 parent.Print(); pp -> Print(); rp.Print(); cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
二。类在C++编译器的内部可以理解为结构体
子类是由父类成员叠加子类新成员得到的
1.在子类对象构造的时候需要调用父类的构造函数对其继承的来的成员进行初始化
2.在子类对象析构的时候需要调用父类析构函数对其继承得来的成员尽心清理
#include <cstdlib> #include <iostream> using namespace std; class Parent { public: Parent() { cout << "Parent()" << endl; } ~Parent() { cout << "~~Parent()" << endl; } }; class Child : public Parent { public: Child() { cout << "Child()" << endl; } ~Child() { cout << "~Child()" <<endl; } }; void run(void) { Child child; } int main(int argc, char *argv[]) { run(); cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
输出结果
3.子类对象在创建时会首先调用父类的构造函数
4.父类构造函数执行结束后,执行子类的构造函数
5.当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
class Parent { public: Parent(const char* s) { cout << "Parent()" <<" "<< s << endl; } ~Parent() { cout << "~~Parent()" << endl; } }; class Child : public Parent { public: Child():Parent("Parameter from Child") { cout << "Child()" << endl; } ~Child() { cout << "~Child()" <<endl; } };
三。继承与组合的混搭
类中成员变量可以是其他类的对象。
问题 : 如果一个类继承自父亲并且有其他的对象作为其成员
口诀:先父母,后客人,最后自己
#include <cstdlib> #include <iostream> using namespace std; class Object { public: Object(const char* s) { cout << "Object()" << " " << s << endl; } }; class Parent : public Object { public: Parent(const char* s):Object(s) { cout <<"Parent()" << " " <<s <<endl; } }; class Child : public Parent { protected: Object o1; Object o2; public : Child():o2("o2"),o1("o1"),Parent("Parameter from Child") { cout << "Child()" <<endl; } }; void run() { Child child; } int main(int argc, char *argv[]) { run(); cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
输出结果
四。同名成员变量
当子类成员变量与父类成员变量同名时
1.子类依然从父类继承同名成员
2.在子类中通过作用域分别符::进行同名成员区分
3.同名成员存储在内存中的不同位置
#include <cstdlib> #include <iostream> using namespace std; class Parent { protected: int i; int f; }; class Child : public Parent { protected: int i; void f() { cout<<"Parent::i = "<<Parent::i<<endl; cout<<"Child::i = "<<Child::i<<endl; cout<<"Parent::f = "<<Parent::f<<endl; } public: Child(int i, int j) { Parent::i = i; Child::i = j; Parent::f = i + j; f(); } }; void run() { Child child(1, 3); } int main(int argc, char *argv[]) { run(); cout << "Press the enter key to continue ..."; cin.get(); return EXIT_SUCCESS; }
五。小结
1.子类对象可以当作父类对象使用
2.子类对象在创建时需要调用父类构造函数进行初始化
3.子类对象在销毁需要调用父类析构函数进行清理
4.先执行父类构造函数,再执行成员构造函数
5.在继承中的析构顺序与构造顺序对称相反
6.同名成员通过作用域分辨符进行区分