标签:
继承是面向对象复用的重要手段。通过继承定义一个类,它们的类型之间的关系建模,共享公有的东西,实现各自本质不同的东西。
继承是一种复用手段,在继承关系里基类的成员类的成员派生类的成员,由此达到复用的目的。
三种继承方式:
公有继承 class A : public B
保护继承 class A : protected B
私有继承 class A : private B
总结:
1. 基类的私有成员在派生类中是不能被访问的,如果一些基类成员不想被基类对象直接访问,但需要在派生类中能访问,就定义为保护成员。可以看出保护成员限定符是因继承才出现的。
2. public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。
3. protetced/private继承是一个实现继承,基类的部分成员并未完全成为子类接口的一部分,是 has-a 的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。
不管是哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,但是基类的私有成员存在但是在子类中不可见(不能访问)。
4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
5. 在实际运用中一般使用都是public继承,极少场景下才会使用protetced/private继承.
继承与转换--赋值兼容规则:
1. 子类对象可以赋值给父类对象
2. 父类对象不能赋值给子类对象
3. 父类的指针/引用可以指向子类对象
4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)
继承体系中的作用域:
1. 在继承体系中基类和派生类都有独立的作用域。
2. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问)--隐藏
3. 注意在实际中在继承体系里面最好不要定义同名的成员。
派生类的默认成员函数
在继承关系里面,在派生类中如果没有显示定义这六个成员函数,编译系统则会默认合成这六个默认的成员函数。
单继承&多重继承
单继承--一个子类只有一个直接父类时称这个继承关系为单继承
多继承--一个子类有两个或以上直接父类时称这个继承关系为多继承
虚函数&多态
虚函数--类的成员函数前面加virtual关键字,则这个成员函数称为虚函数。
虚函数重写--当在子类的定义了一个与父类完全相同的虚函数时,则称子类的这个函数重写(也称覆盖)了父类的这个虚函数。
总结:
派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)
基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
只有类的成员函数才能定义为虚函数。
静态成员函数不能定义为虚函数。
如果在类外定义虚函数,只能在声明函数时加virtual,类外定义函数时不能加virtual。
构造函数不能为虚函数,虽然可以将operator=定义为虚函数,但是最好不要将operator=定义为虚函数,因为容易使用时容易引起混淆。
不要在构造函数和析构函数里面调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会发生未定义的行为。
最好把基类的析构函数声明为虚函数。(why?另外析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里是因为编译器做了特殊处理)
纯虚函数
在成员函数的形参后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。
友元与继承
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
继承与静态成员
基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。
标签:
原文地址:http://blog.csdn.net/zgw285763054/article/details/51320903