c++继承二

c++11继承二

  • 继承与友元

    友元关系不能继承,基类友元不能访问子类私有和保护成员

    class Student;
    class Person
    {
    public:
        friend void print(const Person&, const Student&);
    
    protected:
        string name_{"yker"};
      };
        
        class Student : public Person
        {
        public:
            int num_{2};
        protected:
            int id_;
        };
        
        void print(const Person& p, const Student& s)
        {
            cout << p.name_ << s.name_ << s.num_ << endl;
        }
    

    从例子可以看到 print函数中s对象并不能访问id_成员,原因是id_成员是保护的,相反num_可以被访问

  • 继承与静态成员

    基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生多少个子类,都只有一个static成员

    class Person
    {
    public:
        Person()
        {
            ++count_;
        }
        static int count_;
    };
    int Person::count_ = 0;
    
    class Student : public Person
    {
    private:
        int id_;
    };
    
    void test3()
    {
        Student s1;
        Student s2;
        Student s3;
        cout << Person::count_ << endl; // 3
        Student::count_ = 0;
        cout << Person::count_ << endl; // 0
    }
    

    可以看出count_只有一份

  • 多继承

    一个子类有两个或以上直接父类时称这个继承关系为多继承

    菱形继承是多继承的一种特殊情况

    class Person
    {
    public:
        Person()
        {
            ++count_;
        }
        static int count_;
    };
    int Person::count_ = 0;
    
    class Student : public Person
    {
    private:
        int id_;
    };
    
    class Base
    {
    public:
        int id_{0};
    };
    
    class A : public Base
    {
    private:
        int flag_{1};
    };
    
    class B : public Base
    {
    private:
        int bang_{2};
    };
    
    class C : public A, public B
    {
    private:
        int self_{3};
    };
    void test4()
    {
        C c;
        c.id_ = 2;  // 编译错误
        c.A::id_ = 2; // 正确
    }
    

    对象模型:

    在这里插入图片描述
    由于对象c中有两个继承自Base类的id_成员变量,当我们对其进行初始化或赋值时,就会产生二义性, 编译器并不知道该向哪个id初始化赋值, 所以在对其进行初始化必须带上类名访问

    虽然解决了数据二义性但是数据冗余仍然存在,所以出现了虚继承

    • 虚继承

      class Base
      {
      public:
      	int id_{ 0 };
      };
      
      class A : public Base
      {
      public:
      	int flag_{ 1 };
      };
      
      class B : public Base
      {
      public:
      	int bang_{ 2 };
      };
      
      class C : public A, public B
      {
      public:
      	int self_{ 3 };
      };
      
      void test4()
      {
      	C c;
      	c.A::id_ = 1;
      	c.B::id_ = 2;
      	c.bang_ = 3;
      	c.flag_ = 4;
      	c.self_ = 5;
      }
      

      菱形继承的对象模型

      在这里插入图片描述

      菱形虚继承的对象模型
      在这里插入图片描述

    通过对象模型内存布局可以得出,c对象将Base对象中的成员id_放在了对象组成的最下面,这个Base属于A和B,A和B通过各自的指针指向虚基表,虚基表中存的偏移量,A和B的地址加上偏移量就能找到Base

  • 继承与组合

    • public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象
    • 组合是一种is-a的关系。假设B组合A,每个B对象中都有一个A对象
    • 优先使用组合,而不是继承,破坏分装性
    • 实现多态要用继承

于A和B,A和B通过各自的指针指向虚基表,虚基表中存的偏移量,A和B的地址加上偏移量就能找到Base*

  • 继承与组合

    • public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象
    • 组合是一种is-a的关系。假设B组合A,每个B对象中都有一个A对象
    • 优先使用组合,而不是继承,破坏分装性
    • 实现多态要用继承
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值