C++继承
继承就是类之间的一种关系,子类拥有父类的一切,也能够完成父类的所有可以完成的事务。父类也即基类,子类也即派生类。(子类和基类是相对而言的)。
继承的方式一般写成:
class 子类:继承权限 父类,…,继承权限 父类
因为C++
支持多继承,所以继承列表可以有多个父类,以逗号分隔。
继承权限
继承关键字
C++
提供三个权限关键字:public
、protected
、private
。(一般使用第一种。)
- 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
- 保护继承(protected):当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
- 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
访问控制
继承权限 | public | protected | private |
---|---|---|---|
public | public | protected | private |
protected | protected | protected | private |
private | private | private | private |
访问 | public | protected | private |
---|---|---|---|
同一个类 | √ | √ | √ |
派生类 | √ | √ | × |
外部的类或函数 | √ | × | × |
一个派生类继承了所有的基类方法,以下情况除外:
- 基类的构造函数、析构函数和拷贝构造函数
- 基类的重载运算符
- 基类的友元函数
示例:
//基类
class Shape {
protected:
int x, y;
public:
Shape(int x, int y) {
this->x = x;
this->y = y;
}
};
//基类
class volume {
protected:
int calVolume(int x, int y, int z) {
return x * y * z;
}
};
//派生类
class Cube:public Shape , public volume {
private:
int z;
public :
Cube(int x, int y, int z):Shape(x , y){
this->z = z;
}
int cal() {
return calVolume(x, y, z);
}
};
int main() {
Cube cube(1, 2, 3);
cout << "立方体的体积为:" << cube.cal() << endl;
return 0;
}
输出:立方体的体积为:6
继承的构造与析构
在生成子类对象过程中会首先调用父类构造函数,然后再调用子类构造函数,这样就让父类构造函数把父类部分数据初始化了一遍,然后通过调用子类构造函数初始化子类成员。而对于析构函数就刚好相反了,秉承着先进后出的堆栈思想。
有如下示例:
class A {
public:
A() {cout << "A" << endl;}
~A() { cout << "DA" << endl; }
};
class B {
public:
B() { cout << "B" << endl; }
~B() { cout << "DB" << endl; }
};
class C :public A, public B {
public:
C() { cout << "C" << endl; }
~C() { cout << "DC" << endl; }
};
int main() {
C* c = new C();
delete c;
return 0;
}
输出:类名表示调用了构造函数,在类名前加D表示调用了析构函数
A
B
C
DC
DB
DA
因为在C++
中存在多继承,对于上述程序,若B
也继承于A
,则输出为:
A
A
B
C
DC
DB
DA
DA
发现对象A
被构造了两次,为了解决这一问题,可以在继承关键字前加上virtual
关键字,即:
class A {
public:
A() {cout << "A" << endl;}
~A() { cout << "DA" << endl; }
};
class B:virtual public A {
public:
B() { cout << "B" << endl; }
~B() { cout << "DB" << endl; }
};
class C :virtual public A, public B {
public:
C() { cout << "C" << endl; }
~C() { cout << "DC" << endl; }
};
int main() {
C* c = new C();
delete c;
return 0;
}
输出:
A
B
C
DC
DB
DA
对于上述代码,若删去C
或B
继承的virtual
关键字都会导致编译失败(VS2022
)。
上述添加virtual
关键字的继承方式称为虚继承,虚继承在创建父类对象的时候会创建一个虚表。
改变访问权限
使用 using
关键字可以改变基类成员在派生类中的访问权限,例如将 public
改为 private
、将 protected
改为 public
。
注意:using
只能改变基类中 public
和 protected
成员的访问权限,不能改变 private 成员的访问权限,因为基类中 private
成员在派生类中是不可见的,根本不能使用,所以基类中的 private
成员在派生类中无论如何都不能访问。
实例:
class A {
public:
A(){}
~A(){}
void func() {};
protected:
int a, b, c;
};
class B : public A {
public:
B(){}
~B(){}
using A::a;//将protected改为public
using A::b;
int d;
private:
using A::func;//将public 改为 private
};
参考资料
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。