继承
继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易,达到了重用代码功能和提高执行时间的效果。
当创建一个类时,只需指定新建的类继承了一个已有的类的成员即可。已有的类称为基类(父类),新建的类称为派生类(子类)。
基类 & 派生类
一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。
定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:
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