继承性是面向对象程序设计的最重要的特性,可以这么说,如果没有掌握继承性,就等于没有
掌握类和对象的精华,所以很好的掌握继承性是我们学好C++的基础,下面我们对它进行一一介绍。
继承是面向对象复用的重要手段。通过继承定义一个类,它们的类型之间的关系建模,共享公有的东西,实现各自本质不同的东西。
有三种继承方式:Public继承,Protected继承,Private继承。
总结:
基类的私有成员在派生类中是不能被访问的,如果一些基类成员不想被基类对象直接访问,但需要在派生类中能访问,就定义为保护成员。可以看出保护成员限定符是因继承才出现的。
public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。
protetced/private继承是一个实现继承,基类的部分成员并未完全成为子类接口的一部分,是 has-a 的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。
不管是哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,但是基类的私有成员存在但是在子类中不可见(不能访问)。
使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
在实际运用中一般使用都是public继承,极少场景下才会使用protetced/private继承.
用下面的实例演示三种继承关系下基类成员的各类型成员访问关系的变化
class Person
{
public:
void Display()
{
cout << " _name "<< endl;
}
protected:
string _name; // 姓名
private:
int _age; // 年龄
};
class Student : public Person //此处可以修改继承属性
{
protected:
int _num; // 学号
};
void Test()
{
Person p; //创建了一个基类(父类)类型的对象
Student s;//创建了一个派生类(子类)类型的对象
// 1.子类对象可以赋值给父类对象(切割 /切片)
p = s;
// 2.父类对象不能赋值给子类对象
s = p;
// 3.父类的指针/引用可以指向子类对象
Person* p1 = &s;
Person& r1 = s;
// 4.子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)
Student* p2 = (Student *)& p;
Student& r2 = (Student &)p;
// 这里会发生什么?
p2->_num = 10;
r2._num = 20;
}
以上调试后得到如下结论:
继承与转换--赋值兼容规则
子类对象可以赋值给父类对象(切割/切片)
父类对象不能赋值给子类对象
父类的指针/引用可以指向子类对象
子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)
继承体系中的作用域
在继承体系中基类和派生类都有独立的作用域。
子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问)--隐藏
注意在实际中在继承体系里面最好不要定义同名的成员。
单继承&多重继承
单继承--一个子类只有一个直接父类时称这个继承关系为单继承
多继承--一个子类有两个或以上直接父类时称这个继承关系为多继承
虚继承--解决菱形继承的二义性和数据冗余的问题
虚继承解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余&浪费空间的问题。
虚继承体系看起来好复杂,在实际应用我们通常不会定义如此复杂的继承体系。一般不到万不得已都不要定义菱形结构的虚继承体系结构,因为使用虚继承解决数据冗余问题也带来了性能上的损耗。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。