C++---继承总结

mac2024-07-05  55

继承 继承是面向对象程序设计使用的代码复用的手段,可以在保持原有类的特性的基础上进行扩展,增加新的类。

class Person { public: void Print() { cout << "name: " << name << endl; cout << "age: " << age; } protected: string name = "xiaoming"; int age = 18; }; class Student :public Person { public: void Print() { cout << name<<" "; cout << age<<" "; cout << _Id; } protected: int _Id = 0001; };

先看上面的代码,有两个类,Student类中没有定义name与int成员变量,为什么在Print函数当中,可以输出值呢? 我们把上面这种定义称为,Student类继承Person类,其中Person称为父类(基类),Student称为子类(派生类)。上面的代码可以给出一个简单的解释,儿子可以使用其父亲的一些东西。

继承的定义 继承包括:子类(派生类),继承方式,父类(基类) 父类中有些东西,不想被继承,所以可以通过给变其继承方式来改变。 继承方式: 但不同的继承方式,也会产生不同的变换。 说明:

父类(基类)中的私有成员变量同样被继承到子类(派生类)中,但是对于子类而言,继承父类的私有成员,不论是在子类的类体外还是在类体内,都不能访问。父类的成员(变量、函数)如果不想在类外被访问,但需要在子类中被访问,可以将其成员的访问限定符定义为protected。class默认的访问限定符为private,struct默认的访问限定符为public。在实际中一般都是用public的继承方式。

继承底层数据模型 赋值兼容规则

当继承的方式为public时 子类对象可以直接赋值给父类对象、父类的指针、父类的引用。 Person p; Student s; p = s; Person *pp = &s; Person &p = s;

父类指针可以通过强制类型转换赋值给子类的指针。

Person *pp; Student *ss = (Student*)pp;

继承的作用域—产生同名覆盖问题

在继承体系中,子类与父类都有自己独立的作用域。子类和父类有同名的成员,子类将屏蔽父类对同名函数的直接访问,这就产生了同名隐藏,也称为重定义。如果想访问父类的成员函数可以使用:类名::基类成员只要子类成员名与父类成员名相同时,就构成重名覆盖。 class Person { public: void Print() { cout << "name: " << name << endl; cout << "age: " << age; } protected: string name = "xiaoming"; int age = 18; }; class Student :public Person { public: void Print() { cout << name<<" "; cout << age<<" "; cout << _Id; Person::Print(); //调用父类中的成员函数 } protected: int _Id = 0001; };

派生类的默认成员函数

子类(派生类)的构造函数必须调用父类的构造函数初始化父类的一成员,如果父类没有默认的构造函数,必须在子类中显示调用父类的构造函数子类(派生类)的拷贝构造函数必须父类的拷贝构造函数,完成子类的完全初始化。子类的operator=必须调用父类的operator=完成基类的复制子类的析构函数首先调用完自己的析构函数后,会主动调用父类的析构函数。(先清理子类部分再清理父类)子类构造先调用父类的构造,在调用自己的构造 class Person { public: Person(const char* name = "xiaoming") :_name(name) { cout << "Person()" << endl; } Person(const Person& s) :_name(s._name) { cout << "Person(const Person&)" << endl; } Person& operator = (const Person& s) { if (this != &s) { _name = s._name; } cout << "Person operator " << endl; return *this; } ~Person() { cout << "~Person" << endl; } protected: string _name; // 姓名 }; class Student :public Person { public: Student(const char* name, int _age) :Person() ,age(_age) { cout << "Student()" << endl; } Student(const Student& s) :Person(s) ,age(s.age) { cout << "Student(const Student&)" << endl; } Student& operator = (const Student& s) { if (this != &s) { cout << "Student operator = " << endl; } return *this; } ~Student() { cout << "~Student()" << endl; } private: int age; };

继承与友元 友元关系不能被继承。基类的友元函数,不能访问子类的成员。例如:父亲的朋友,不是你的朋友。

继承与静态成员 基类定义了一个static成员,则整个继承体系中只有一个静态成员。

class Person { public: Person() //每次调用Person时,count++ { ++_count; } static int _count; }; int Person::_count; class Student :public Person { protected: int _num; }; class Graduate:public Student { protected: string _seminarCourse; };

菱形继承—钻石继承

单继承:一个子类只有一个父类 多继承:一个子类有多个父类 菱形继承是多类型的一种:B继承A,就对A的数据保存一份,C继承A,就对A的数据保存一份,当D多继承B,C就会对A的数据保存两份,所以会造成数据冗余与二义性。

解决方式:菱形虚拟继承。(详见下面链接) https://blog.csdn.net/qq_42708024/article/details/104318891

最新回复(0)