c++继承一
-
不同访问限定符的继承变化
使用class时默认的继承方式是private,使用struct时默认的继承方式是public -
基类和派生类对象赋值转换
- 派生类对象可以赋值给基类的对象/基类的指针/基类的引用,叫做切片
- 基类对象不能赋值给派送类对象
- 基类的指针可以通过强制类型转换赋值给派生类的指针这是c语言的锅。但是必须是基类的指针是指向派生类对象时才是安全的。如果基类是多态类型(具有虚函数),可以使用dynamic_cast来进行识别后进行安全转换
class Person { public: void print() { std::cout << name_ << age_ << std::endl; } private: int age_{20}; std::string name_{"yker"}; }; class Student: public Person { public: void print() { std::cout << "drive" << std::endl; } private: int id_{1}; }; int main() { // 隐藏 Student stu; Person per = stu; Person* perp = &stu; Person& pr = stu; per.print(); perp->print(); pr.print(); return 0; }
通过调试可以看到per对象、指针、引用中并没有id_成员,在这发生了切边
-
继承中的作用域
- 在继承中基类和派生类都有独立的作用域
- 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况将隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显式访问)
- 成员函数的隐藏,只需要函数名相同就构成隐藏
在上面的例子中我在派生类中也定义了print函数,当使用派生类对象调用时print函数时调用的是派生类函数,父类print函数被隐藏。
-
派生类的默认成员函数
- 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
- 派生类的构造拷贝函数必须调用基类的构造拷贝完成基类的拷贝初始化
- 派生类的operator=必须要调用基类的operator=完成基类的复制
- 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类的成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序
- 派生类对象初始化先调用基类构造再调派生类构造
- 派生类对象析构清理先调用派生类析构再调基类的析构
class Person { public: Person(const char* name = "yker") : name_(name) { cout << "Person" << endl; } Person(const Person& per) : name_(per.name_) { cout << "Person(const Person&)" << endl; } Person&operator=(const Person& per) { if (this != &per) name_ = per.name_; cout << "operator=" << endl; return *this; } ~Person() { cout << "~Person" << endl; } private: string name_; }; class Student: public Person { public: Student(const char* name, int id) : Person(name), id_(id) { cout << "Student" << endl; } Student(const Student& stu) : Person(stu), id_(stu.id_) { cout << "Student(const Student&)" << endl; } Student&operator=(const Student& stu) { if (this != &stu) { Person::operator=(stu); id_ = stu.id_; } cout << "Student operator=" << endl; return *this; } ~Student() { cout << "~Student" << endl; } private: int id_; }; void test1() { Student s1("yker", 21); Student s2(s1); Student s3("zrn", 20); s1 = s3; }
-
实现一个不能被继承的类
// c++98 class NonInherit { public: static NonInherit GetInstance() { return NonInherit(); } private: NonInherit() {} } // c++11 class NonInherit final { };