c++那些事儿3.0 继承

    一般形式   
     class class_name:继承方式 基类名{ code   }
         继承方式有三种: public ,protected,private.   //java好像都是public继承。
     单继承
     多继承,多继承会很复杂,所以java,c sharp都采用interface。
  类函数:
     构造函数
           先执行父类的构造函数,在执行子类的构造函数。
           一般形式  派生类的构造函数(参数列表):基类构造函数名(参数列表}{ code}
     析构函数
           先构造的后析构,后构造的先析构。
     虚函数。
     避免二义性。但是最后的派生类不仅负责对直接基类初始化,还要对虚基类初始化。



看code是最有用的,细节情况已经注释说明。

#include<iostream>
#include<string>
using namespace std;
     // 类A
class A {
  protected:
    string name;
    int id;
    double da;
private:
    double pa; //这个数据继承后不能被访问
 public:
     A(string name, int id) {
         cout << "A的构造函数执行"<<endl;
         this->name = name;   //this指针
         this->id = id;
         this->da = da;
     }

     void setDa(double d) {
         da = d;
     }

     ~A() {
         cout << "A的析构函数"<<endl;
     }

    void setId(int id) {
//id是私有数据成员,不能被继承,类外不能访问,通过函数才能
        this->id = id;
     }

     void print() {
         cout << "string=" << name << "  " << "id=" << id<< endl;
     }

};
// 注意 C++中类的结尾是有;的,和java不同,我vs,ide编辑没有在意。

//如果不写关键字,默认为private。
class B :virtual public A {
    //B类public继承A类,但是私有数据成员不能访问。
  protected:
    int id;  //A类的id成员被覆盖了。

  public:
  /*
  父类构造函数的初始化通过子类构造函数初始化列表实现,
  */
    
      B(string na,int ida,int idb):A(na,ida){
          cout << "B的构造函数执行"<<endl;
          this->id = idb;
      }
      ~B() {
          cout << "B的析构函数"<<endl;
      }

      void  print() {
          /*
          基类同名的数据成员在派生类被覆盖,成为不可见。
          */
          cout << "A类被继承的ID:" << A::id << endl;
          cout <<"name:B"<< name<<" "<<"id:"<<id<<endl; //name是继承A的。
      }

};

class C:virtual public A{

    //B类public继承A类,但是私有数据成员不能访问。
protected:
    int id; 

public:
    /*
    父类构造函数的初始化通过子类构造函数初始化列表实现,
    */
    C(string na,int ida,int idc) :A(na,ida) {
        cout << "C的构造函数执行" << endl;
        this->id = idc;
    }
    ~C() {
        cout << "C的析构函数" << endl;
    }

    void  print() {
        cout << "name:C" << name << " " << "id:" << id << endl;; //name是继承A的。
        
    }
};

//D类继承B,C, 因为B,C都继承A,所以D类有2份A,这样就会出现二义性问题。
class D :public B,public C {
 public:
     void showId() {
        /* cout << "id::" << id << endl;
           如果这样,就会产生二义性,D公有继承了B,C protedted的id,
           这里不知道访问哪一个。 但是可以通过域运算符指定A,B,C继承来的id。
        */
         cout << "id::A" <<A::id << endl;
                  //通过域运算符指定id。
     }

     /*
      D继承了,B,C。B,C继承了A,即继承了double da;
      怎么访问它了。
          cout<<da;
          cout<<A::da; 都不行,无法指出是继承B的,还是C的。
           所以就要虚基类了。
     */
     void showDa() {

         cout << "B::da" << B::da << endl;
     }
     /*
     在以前派生类只对其直接基类初始化,在由其直接子类对间接子类初始化
     现在由于虚基类在派生类只有一份拷贝,所以这份数据必须由派生类给出。
     因为类B,类C可能给出不同的构造函数,这样对虚基类初始化会产生矛盾。
     */

     D(string na, int ida, int idc) :C(na, ida, idc),
         B(na, ida, idc), A(na, ida)
     {
         cout << "D的构造函数执行" << endl;
     }
     ~D() {
         cout << "D的析构函数" << endl;
     }

 
};

int main() {


    A a("name_A", 111);
    a.print();
    cout << "-----------------------------" << endl;
    //先执行父类的构造函数,在执行基类的构造函数
    B b("name_B",111, 222);
    //这里是B的id,因为private属性在子类不能访问。
    b.print();
    cout << "-----------------------------" << endl;
    C c("name_C", 111, 333);
    //这里是B的id,因为private属性在子类不能访问。
    c.print();
    cout << "-----------------------------" << endl;


    D d("name_D", 111, 444);

    // id的二义性 可以通过 ::域运算符指定,解决。
       d.showId();

     // 准备验证double da; 产生二义性的情况,这个就只能通过虚基类确定。
      //   setDa() 是会产生二义性的函数,但是A是虚基类。
       d.setDa(3.1415926);
       d.showDa();
       cout << "-----------------------------" << endl;

    
     system("pause");  //vs要看析构函数要去掉这一句。
    return 0;
}


结果如下,可以对照代码分析

结果图.PNG

这里main函数的代码如下:

int main() {
       D d("name_D", 111, 444);
    // id的二义性 可以通过 ::域运算符指定,解决。
       d.showId();

     // 准备验证double da; 产生二义性的情况,这个就只能通过虚基类确定。
      //   setDa() 是会产生二义性的函数,但是A是虚基类。
       d.setDa(3.1415926);
       d.showDa();
       cout << "-----------------------------" << endl;

                                     /*  vs选择开始执行但不调试 */
    // system("pause");  //vs要看析构函数要去掉这一句。
    return 0;
}


构造函数和析构函数执行顺序验证

只保留了D类.PNG



东西好多啊,c++ 讲个语法就不少东西了

 虚函数,多态性,这个代码挖了坑,后面在讲,好累啊。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.面向对象的程序设计思想是什么? 答:把数据结构和对数据结构进行操作的方法封装形成一个个的对象。 2.什么是类?...
    少帅yangjie阅读 5,051评论 0 14
  • 一、 C/C++程序基础 面试例题1——分析代码写输出(一般赋值语句的概念和方法)。 面试例题2—...
    LuckTime阅读 2,022评论 2 42
  • 姓名:程英鑫 学号:16020140082 学院:电子工程学院 转载自:头条号 有删减 【嵌牛导读】:每当浏...
    落意秋浓阅读 390评论 0 0
  • 不减肥的结果,老板,来两碗,管饱就行。。。吃货在下那么大的雷阵雨,依然执着前往可以一家,比较温馨的米线馆,小城在午...
    杨二灿阅读 230评论 0 0
  • 2017 11 15 晴 星期三 儿子晚上回来,自己进房间写作业,我抱着二宝,时不时的偷偷的瞄一眼,看看是不...
    99d29bce557c阅读 144评论 0 0