继承:龙生龙,凤生凤,老鼠儿子会打洞。
sizeof可以验证继承了基类中的所有成员变量
public 的继承方式,结合子类对象对基类成员函数的调用,可以得到子类对基类的成员函数继承(所有资源都被继承。基类中public成员在子类中权限也是public。)
#include<iostream> using namespace std; class Base { //父类 public: void Set(int pri,int pro,int pub) { _pri = pri; _pro = pro; _pub = pub; } void Print() { cout << _pri << " " << _pro << " " << _pub << endl; } int _pub; protected: int _pro; private: int _pri; }; class Son1 : Base //子类 //无继承方式 { }; class Son2 : public Base //子类 //public继承方式 { public: void Set(int pri, int pro, int pub) { _pri = pri; //这句报错:在子类中访问私有的成员变量不可以访问。 _pro = pro; //保护可以访问 _pub = pub; } }; int main() { cout << sizeof(Son1) << endl; //大小是12; 成员变量能够继承 Son1 s; s.Set(); s.Print(); //这样就报错了,因为需要有继承方式 system("pause"); return 0; }
继承方式:
public、private、protected
1.public :所有资源都被继承。基类中public成员变量在子类中权限也是public;基类中保护的成员变量在子类中直接访问其访问权限也是保护的,但是在类外不行;基类中私有的成员变量在子类中是是存在的但看不见。(想让后代知道,不想让别人知道。所以保护的可以访问,私有的不能访问)
2.protected:基类中public成员变量在子类中权限发生改变,是protect(类中能访问,类外不能访问);基类中保护的成员变量在子类中访问权限也是保护的,但是在类外不行;基类中私有的成员变量在子类中是是存在的但看不见。
3.private:基类中public成员变量在子类中权限发生改变,是private(类中能访问,类外不能访问);基类中保护的成员变量在子类中访问权限也是protect,但是在类外不行;基类中私有的成员变量在子类中是是存在的但看不见
实际运用几乎都是public。(图中的成员权限是基类的)
赋值兼容规则:
子类对象可以当作父类对象使用;
子类对象可以直接赋值给父类对象;
子类对象可以直接初始化父类对象;
父类指针可以直接指向子类对象;
父类引用可以直接引用子类对象;
在替代之后,派生类对象就可以作为基类的对象使用,但是只能使用从基类继承的成员。
子类就是特殊的父类。同名成员变量和成员函数通过作用域分辨符进行区分。
判断某一句话,能否被访问:
1.看调用语句,这句话写在子类的内部、外部
2.看子类如何从父类继承(public、private、protected)
3.看父类中的访问级别(public、private、protected)
如何恰当的使用public,protected和private为成员声明访问级别:
1.需要被外界访问的成员直接设置为public
2.只能在当前类中访问的成员设置为private
3.只能在当前类和子类中访问的成员设置为protected,protected成员的访问权限介于public和private之间。
一般情况下用public。
继承的构造函数和析构函数:
如何初始化父类成员?父类与子类的构造函数有什么关系?
1.在子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化
2.在子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理
继承中的构造析构调用原则
1.子类对象在创建时会首先调用父类的构造函数
2.父类构造函数执行结束后,执行子类的构造函数
3.当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
4.析构函数调用的先后顺序与构造函数相反
多继承:
一个类有多个直接基类的继承关系称为多继承。
格式:class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n
多继承的派生类构造和访问:
1.多个基类的派生类构造函数可以用初始式调用基类构造函数初始化数据成员
2.执行顺序与单继承构造函数情况类似。多个直接基类构造函数执行顺序取决于定义派生类时指定的各个继承基类的顺序。
3. 一个派生类对象拥有多个直接或间接基类的成员。不同名成员访问不会出现二义性。如果不同的基类有同名成员,派生类对象访问时应该加以识别。
虚继承:
如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的名字进行访问时,可能产生二义性。
友元函数:
1.友元函数不是类成员函数,所以不能被继承;
2.友元关系是单向的,不具有交换性;若B类是A类的友元,不一定A类就是B类的友元
3.友元关系不能被传递,若B类是A类的友元,C类是B类的友元,C类不一定是A类的友元
友元函数注意事项:
1.友元函数可访问类的私有成员,但不是类的成员函数;
2.友元函数不能用const修饰;
3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制;
4.一个函数可以是多个类的友元函数;
5.友元函数的调用与普通函数的调用和原理相同;
6.友元关系不能继承,基类的友元对派生类的成员没有特殊的访问权限。如果基类被授予友元关系,则只有基类具有特殊的访问权限。该基类的派生类不能访问授予友元关系的类。
class Base { friend void fun(); public: Base(int a = 0, int b = 0, int c = 0) : _pub(a) , _pro(b) , _pri(c) {} int _pub = 1; protected: int _pro = 2; private: int _pri = 3; }; class Derive :public Base {}; int main() { Derive d1; d1.fun(); return 0; }
结果是报错:fun函数不是派生类的成员函数,说明friend函数不能被继承。