C++学习笔记8:继承与派生

继承

继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易,达到了重用代码功能和提高执行时间的效果。

当创建一个类时,只需指定新建的类继承了一个已有的类的成员即可。已有的类称为基类(父类),新建的类称为派生类(子类)。

基类 & 派生类
一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。
定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:
class derived-class: access-specifier base-class
其中,访问修饰符 access-specifier 是 public、protected 或 private 其中的一个,base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier,则默认为 private。(默认私有继承)

假设有一个基类 Shape,Rectangle 是它的派生类,如下所示:

// 基类
class Shape {
   public:
      void setWidth(int w) {
         width = w;
      }
      void setHeight(int h) {
         height = h;
      }
   protected:
      int width;
      int height;
}; 
// 派生类
class Rectangle: public Shape{
   public:
      int getArea(){ 
         return (width * height); 
      }
}

派生类有width,height成员和setWidth, setHeight成员函数,还有getArea成员函数

final关键字:不重写/不继承

父类的虚函数或纯虚函数在子类中依然是虚函数。有时我们并不希望父类的某个函数在子类中被重写,在 C++11 及以后可以用关键字 final 来避免该函数再次被重写

class Base{
    public:
        virtual void func(){cout<<"This is Base"<<endl;}
};
class _Base:public Base{
    public: //正确,func在Base中是虚函数
        void func() final{cout<<"This is _Base"<<endl;}
};
class __Base:public _Base{
/*    public://不正确,func在_Base中已经不再是虚函数,不能再被重写
        void func(){cout<<"This is __Base"<<endl;}
*/
};

此时,func()在_Base中不是虚函数,且不能再被重写

如果不希望一个类被继承,也可以使用 final 关键字。该类将不能被继承。

class Class_name final
{
    ...
};

访问控制

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。
一个派生类继承了所有的基类方法,但不包括:

  • 基类的构造函数、析构函数和拷贝构造函数。
  • 基类的重载运算符。
  • 基类的友元函数。

继承类型

当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。
几乎不使用 protected 或 private 继承,通常使用 public 继承。

继承类型描述
公有继承(public)当一个类派生自公有基类时,基类的成员将成为派生类的同类型成员。(不变)
保护继承(protected)当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员
私有继承(private)当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员

派生类内不管是public、protected、private继承,总是可以访问基类的public、protected成员。只不过基类中的private成员永远不能在派生类中访问,不管用什么方式继承。

多继承

多继承即一个子类可以有多个父类,它继承了多个父类的特性。

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};
// 基类 Shape
class Shape {
   public:
      void setWidth(int w){ width = w;}
      void setHeight(int h){height = h;}
   protected:
      int width;
      int height;
}; 
// 基类 PaintCost
class PaintCost {
   public:
      int getCost(int area){return area * 70;}
};
 
// 派生类
class Rectangle: public Shape, public PaintCost{
   public:
      int getArea(){ return (width * height); }
};

另外多继承(环状继承),A->D, B->D, C->(A,B),例如:

class D{......};
class B: public D{......};
class A: public D{......};
class C: public B, public A{.....};

这个继承会使D创建两个对象,要解决上面问题就要用虚拟继承格式

class D{......};
class B: virtual public D{......};
class A: virtual public D{......};
class C: public B, public A{.....};

虚继承–(在创建对象的时候会创建一个虚表)class 类名: virtual 继承方式 父类名

#include <iostream>
using namespace std;
class D{
public:
    D(){cout<<"D()"<<endl;}
    ~D(){cout<<"~D()"<<endl;}
protected: int d;
};

class B:virtual public D{
public:
    B(){cout<<"B()"<<endl;}
    ~B(){cout<<"~B()"<<endl;}
protected:int b;
};

class A:virtual public D{
public:
    A(){cout<<"A()"<<endl;}
    ~A(){cout<<"~A()"<<endl;}
protected:int a;
};

class C:public B, public A{
public:
    C(){cout<<"C()"<<endl;}
    ~C(){cout<<"~C()"<<endl;}
protected:int c;
};

int main(){
    cout << "Hello World!" << endl;
    C c;   //D, B, A ,C
    cout<<sizeof(c)<<endl;
    return 0;
}

构造函数顺序为:D B A C

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值