c++继承知识总结

来源:互联网 发布:黑龙江科技大学网络课 编辑:程序博客网 时间:2024/06/08 05:09

 c++继承相关知识总结

继承关系:public protected private 
 
 不矫情 直接贴代码 举例
  代码主要从:
a. 基类成员对其对象的可见性:  只有public成员可以访问
b. 基类成员对派生类的可见性:  
c. 基类成员对派生类对象的可见性:
  父类(基类) 

class Base{public:Base(){_pri = 1;_pro = 2;_pub = 3;}private:int _pri;protected:int _pro;public:int _pub;};

 (1)public 继承方式
 
class Derived1 :public Base{public:Derived1(){_d1_pri = 4;_d1_pro = 5;_d1_pub = 6;}void showd(){_pub = 0;   // 仍为public成员_pro = 2;   //  仍为protected成员//_pri = 3; // 父类私有成员对子类 不可见}private:int _d1_pri;protected:int _d1_pro;public:int _d1_pub;};void TestPublic(){Base b;b._pub = 1;//b._pro = 2;  // 父类对象不可访问父类保护成员//b._pri = 3;  // 父类对象不可访问父类私有成员Derived1 d1;d1._pub = 1; // 子类对象可以访问父类公有成员//d1._pro = 2; //子类对象不可访问父类保护成员//d1._pri = 3; // 子类对象不可访问父类私有成员d1._d1_pub = 4;}
(2) protected继承
  
// protected 保护继承class Derived2 :protected Base{public:Derived2(){_d2_pri = 4;_d2_pro = 5;_d2_pub = 6;}void showd(){_pub = 1;   //  变为子类的protected成员_pro = 2;   //  仍为protected成员//_pri = 3; // 父类私有成员对子类不可见}private:int _d2_pri;protected:int _d2_pro;public:int _d2_pub;};void TestProtected(){Base b;b._pub = 1;//b._pro = 2;  // 父类对象不可访问父类保护成员//b._pri = 3;  // 父类对象不可访问父类私有成员Derived2 d2;//d2._pub = 1; // 父类的public成员权限被修改为protected,子类对象不可访问//d2._pro = 2; //子类对象不可访问父类保护成员//d2._pri = 3; // 子类对象不可访问父类私有成员d2._d2_pub = 4;}
(3)私有继承
// private私有继承class Derived3 :private Base{public:Derived3(){_d3_pri = 4;_d3_pro = 5;_d3_pub = 6;}void showd(){_pub = 1;   //  变为子类的privite成员_pro = 2;   //  变为子类的privite成员//_pri = 3; // 父类私有成员对子类不可见}private:int _d3_pri;protected:int _d3_pro;public:int _d3_pub;};void TestPrivate(){Base b;b._pub = 1;//b._pro = 2;  // 父类对象不可访问父类保护成员//b._pri = 3;  // 父类对象不可访问父类私有成员Derived3 d3;//d3._pub = 1; // 父类的public成员权限被修改为private,子类对象不可访问//d3._pro = 2; // 父类的protected成员权限被修改为private,子类对象不可访问//d3._pri = 3; // 子类对象不可访问父类私有成员d3._d3_pub = 4;}
   总结一下继承方式 
    1 基类的private成员在派生类中是不能被访问的,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
    2不管是哪种继承方式在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见(不能访问)。
    3 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
 派生类(子类)的默认成员函数
  
  1 继承关系中构造函数和析构函数
   (1)继承关系中的构造函数和析构函数的调用
           构造函数的调用顺序 :Derived d;
     
        析构函数的调用顺序 :
       
             
说明:
       a 、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
       b、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
       c、基类定义了带有形参表构造函数,派生类就一定定义构造函数 (无参或者带参)

 代码举例
     
<span style="font-size:18px;">class A{public:    A(){cout<<"this is A::A()"<<endl;}    A(int b){cout<<"this is A::A(int b):    the value of b is: "<<b<<endl;}    A(double b){cout<<"this is A::A(double b)    the value of b is: "<<b<<endl;}};class B:public A{public:    B():A(){}  //调用基类 A 默认构造函数    B(int b):A(b){} //调用基类 A 的 A::A(int b) 构造函数    B(double b):A(b){} //调用基类 A 的 A::A(double b) 构造函数};void main(){    B b0,b1(5),b2(10.5);//产生三个实例,分别调用不同的基类构造函数    system("pause");}/***********************************调用 func 函数的输出结果:this is A::A()this is A::A(int b):    the value of b is: 5this is A::A(double b)    the value of b is: 10.5***********************************/</span>


   
  2继承体系中的作用域
   2.a. 在继承体系中基类和派生类是两个不同作用域。
   2.b. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基   类 成员 访问)--隐藏 --重定义
   2.c. 注意在实际中在继承体系里面最好不要定义同名的成员。
 3继承与转换--赋值兼容规则--public继承  
记忆法: 大的可以赋值给小的
      注意:只有public继承才有
   3.a. 子类对象可以赋值给父类对象(切割/切片)
   3.b. 父类对象不能赋值给子类对象
   3.c. 父类的指针/引用可以指向子类对象
   3.d. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成) 
    
 4 友元与继承
  友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员
 
  注意下面的例子:<<运算符的重载函数 不能说明友元关系可以继承

<span style="font-size:18px;">class Base{public:friend ostream& operator<<(ostream& _cout,Base &base){_cout << base._pri << endl;return _cout;}private:int _pri;};class Derived :public Base{};void TestBase(){Base b;cout << b; Derived d;cout << d; // 参数发生类型转换 派生类对象赋值给基类对象}</span>

三 继承方式 单继承 多继承( 菱形继承)
  单继承 
   
class A{public:A(){_a = 1;}public:int _a;};class B: public A{public:B(){_b = 2;}public:int _b;};// 创建一个B 类的对象b   查看内存 0x004FFAD8  00000001 00000002 

单继承的数据模型

 多继承(普通)
 
class A{public:A(int a):_a(a){}public:int _a;};class B{public:B(int b):_b(b){}public:int _b;<strong></strong>};class C:public A,public B{public:C(int a,int b,int c): B(a)   //  不是按初始化顺序来初始化派生类的, A(b)   //  而是按继承顺序 public A public B  来调用其构造函数, _c(c){}public:int _c;};//创建一个C 类的对象c   查看内存 0x0023F904  00000002 00000001 00000003
  数据模型:
   

   多继承中的菱形继承(也叫钻石继承)
 
class A{public:A(int a = 0){}public:int _a;};class B1:public A{public:B1(int b):_b1(b){}public:int _b1;};class B2 :public A{public:B2(int b2):_b2(b2){}public:int _b2;};class C :public B1,public B2{public:C(int b1,int b2,int c): B1(b1), B2(b2), _c(c){}public:int _c;};void testD(){C c(1,2,3);c.B1::_a = 4; // 必须指定_a的作用域 不然不知道_a属于B1 还是B2c.B2::_a = 5; // 因此这样就存在二义性 }

数据模型
  
  
 由于存在二义性 因此引入虚继承

虚继承:
 
class A{public:A(int a = 0){_a = a;}public:int _a;};class B1:virtual public A{public:B1(int b):_b1(b){}public:int _b1;};class B2 :virtual public A{public:B2(int b2):_b2(b2){}public:int _b2;};class C :public B1,public B2{public:C(int b1,int b2,int c): B1(b1), B2(b2), _c(c){}public:int _c;};void testD(){cout << sizeof(C) << endl; // 24  B1的大小(8)+B2的大小(8)+C的成员变量(4) =20 多了4个字节C c(1,2,3);//c._a = 1; // 这样就不用作用域限定来指定_a所属}
 数据模型:
  


关于 继承这块 就给大家分享这么多了,欢迎大家指错




3 0
原创粉丝点击