四、派生类的默认成员函数
- 6个默认成员函数示图:
注:“默认”即指我们不写,编译器会自动生成
- 派生类中成员函数是如何生成:
- 示例:
class Person { public: Person(const char* name="Peter") : _name(name) { cout << "Person()" << endl; } Person(const Person& p) : _name(p._name) { cout << "Person(const Person& p)" << endl; } Person& operator=(const Person& p) { cout << "Person operator=(const Person& p)" << endl; if (this != &p) _name = p._name; return *this; } ~Person() { cout << "~Person()" << endl; } protected: string _name; // 姓名 }; class Student : public Person { public: Student(const char* name, int num) : Person(name) , _num(num) { cout << "Student()" << endl; } Student(const Student& s) : Person(s) , _num(s._num) { cout << "Student(const Student& s)" << endl; } Student& operator = (const Student& s) { cout << "Student& operator= (const Student& s)" << endl; if (this != &s) { Person::operator =(s); _num = s._num; } return *this; } ~Student() { cout << "~Student()" << endl; } protected: int _num; //学号 }; void Test() { Student s1("jack", 18); Student s2(s1); Student s3("rose", 17); s1 = s3; }
注意:
派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员;如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用
注:默认构造函数:无参的构造函数,编译器自动生成的构造函数,全缺省的构造函数
示图:无默认构造函数,且不显示调用
派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化
注:如果不调用,系统会自动调用父类的默认构造函数
示图:
注:调用基类的拷贝构造运用了切片操作
派生类的operator=必须要调用基类的operator=完成基类的复制
注:这里的调用赋值同样也是切片操作,如果不主动调用父类赋值重载,则不会完成父类的赋值
派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员,因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序
示图:
注:一般不自行去主动调用基类的析构函数,不然可能会造成错误
派生类对象初始化先调用基类构造再调派生类构造
派生类对象析构清理先调用派生类析构再调基类的析构
示图:
五、继承和友元
- 概念:
友元关系不能继承,即基类友元不能访问子类私有和保护成员(友元只是单向的,无法传递和继承)
- 示例:
class Student; class Person { public: friend void Display(const Person& p, const Student& s); protected: string _name; // 姓名 }; class Student : public Person { protected: int _stuNum; // 学号 }; void Display(const Person& p, const Student& s) { cout << p._name << endl; cout << s._stuNum << endl; }
六、继承和静态成员
- 概念:
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员,无论派生出多少个子类,都只有一个static成员实例
- 示例:
class Person { public: Person() { ++_count; } protected: string _name; // 姓名 public: static int _count; // 统计人的个数 }; int Person::_count = 0; class Student : public Person { protected: int _stuNum; // 学号 }; class Graduate : public Student { protected: string _seminarCourse; // 研究科目 }; void TestPerson() { Student s1; Student s2; Student s3; Graduate s4; cout << " 人数 :" << Person::_count << endl; Student::_count = 0; cout << " 人数 :" << Person::_count << endl; }