类的继承性

43 篇文章 1 订阅

c++中类有三大特性:封装性 继承性和多态性

 

继承目的:在C++中,继承最主要的目的是提供代码的可重用性

继承:如何判断类与类之间存在着继承呢?可通过类与类之间的关系:is-a

如果两个类存在is-a的关系,那么,它们就可以使用继承

has -- a 是一种包含和组合的关系,比如:电脑包含CPU,主板,硬盘

1 继承与组合及继承方式

语法:
父类(基类)
子类(派生类)
class 派生类:[继承方式] 基类名
{
    派生类
}

继承方式:private(默认继承方式) --- 私有继承
         public---公有继承
         protected --- 保护继承
继承方式跟类成员访问修饰符关键字是一样,但是他们的意义不一样
  一个是派生类从基类所继承的方式
  另一个是类中成员对外部和内部的访问权限
       对于访问权限修饰符,在一个类中,private和protectd修饰的类成员,完全一
       样,而在继承中他们有所不同
继承的分类:
单继承 :派生类只有一个基类
多继承:派生类可以同时有多个基类

派生类与基类成员关系:派生类对基类成员是全盘接收,除了构造函数和析构函数

派生类内存分配空间:

继承方式所得出的结论:

public protected private -----> 基类中成员所对应的访问权限修饰符

        公有继承(public) public protected 不可见 -----> 基类中的成员通过继承在派生类所体现的成员访问权限

        保护继承(protectd)protected protected 不可见

        私有继承(private) private private 不可见

2 继承中的构造和析构

情况一: 派生类没有其他类类型

派生类的构造:先调用基类的构造函数,再调用派生类构造函数

派生类的析构:先调用派生类的析构函数,再调用基类的析构函数

情况二:派生类中有类类型

//派生类的构造:

//若派生类有内嵌类型声明,基类构造 ----> 内嵌子对象构造函数(如果有多个内嵌对象,调用顺序跟声明顺序有关) ---> 派生类构造

//析构顺序:派生类 ---- 内嵌子对象 --- 基类,与构造的顺序相反

   //为了解决基类的成员初始化问题,在派生类引入构造函数初始化列表来进行
    Derived(int t =0,int b = 2,const Test& t1 = 0):Base(b),d(t),t1(t1)
    {
        cout << "Derived(int t =0,const Test& t1 = 0)" << endl;
       // this->setB(b); //不建议
       // this->Base(b); error 构造函数不会被派生继承
    }

一 Shadow现象-----继承中同名变量和成员函数

Shadow现象,不是必须会发生,Shadow时机,会发生在基类和派生类中出现重名成员 (包括成员变量和成员函数),此时,派生类会shadow所有父类中的重名成员。 若要使用父类的重名成员,必须通过 类名::来限定重名成员的作用域。

//Shadow(影子 隐藏)
class A
{

public:
    void printT()
    {
        cout << " A::printT()" << endl;
    }
};

class B:public A
{

public:
    void printT()
    {

        cout << " B::printT()" << endl;

        //本意是调用父类的接口printT()
        //printT();  //相当于this->printT();
        A::printT();  //A:: 不是指调用,而且限定函数的作用域
    }
};
int main()
{
   B b;
   //在调用时候,不会出现朝二义性,会调用子类中的函数
   b.printT();

   A a = b; //使用子类对象来初始化父亲的对象
   a.printT(); //调用的是A类(基类)还是B类(派生)中 // 调用基类中成员函数

   A& aa = b; //
   A* pa = &b;

    return 0;
}

二 多继承

一个派生类可以有多个基类

语法:

class 派生类:继承方式 基类1, 继承方式 基类2
{
    
}
比如:
class SafaBed:public Safa,public Bed
{
    
}

 

在多继承中,多个基类中重名的成员,继承到派生类中,为了避免冲突,携带了各基类的 作用域信息,派生类要访问继承下来的和重名成员,访问时需要提供基类的作用域限定信息  

class SaFa
 {
public:
    int m; //材质
};

class Bed
{

public:
    int m; //材质
};

class SaFaBed:public Bed,public SaFa
{
  //对于派生类中,从不同的基类中,继承得到相同名字成员 --- 三角问题
    //1.数据冗余
    //2.重名成员,使用起来不方便
//为了解决三解,在C++中,有了更好解决方案:将三角转四角(菱形)
    /*
    1,提取公因式,提取各基类中相同的成员,构成祖父类(虚基类)
    2.让各基类,继承祖父类,继承的方式,采用虚继承
    3.虚继承是继承的一种扩展
   */
public:
    void printSB()
    {
        //main.cpp:25:11: error: member 'm' found in multiple base classes of different types
       // main.cpp:15:9: note: member found by ambiguous name lookup
       // main.cpp:8:9: note: member found by ambiguous name lookup
          SaFa::m = 10;
          Bed::m = 30;
          sb = 20;

          cout << SaFa::m <<" ---" << Bed::m << " ----" << endl;
    }
    int sb;
};
int main()
{
   SaFaBed s;
   s.printSB();
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值