继承
文章源地址:修能的博客
什么是继承
在C++中,继承是一种对象-oriented(面向对象)编程的特性,它允许你创建一个新的类(称为子类或派生类),并从一个现有的类(称为父类或基类)中继承属性和方法。
通过继承,子类可以继承父类的数据成员和成员函数,并且还可以添加自己的数据成员和成员函数。这意味着子类可以重用父类的代码,并且可以通过添加新的功能来扩展它。
继承可以分为不同的类型:
- 公有继承(public inheritance)
- 私有继承(private inheritance)
- 保护继承(protected inheritance)
这些不同的类型决定了子类对父类成员的访问权限。
公有继承
class A{
public:
int a;
protected:
int b;
};
class B : public A{
public:
int a;
protected:
int b;
};
公有继承(public inheritance)是C++中最常见的一种继承方式。
在公有继承中,子类继承了父类的所有公有成员和保护成员。这意味着子类可以访问父类的公有成员和保护成员,但不能访问父类的私有成员。
保护继承
class A{
public:
int a;
protected:
int b;
};
class B : protected A{
protected:
int a;
int b;
};
保护继承(protected inheritance)是C++中另一种继承方式。
在保护继承中,子类继承了父类的所有保护成员和公有成员。这意味着子类可以访问父类的保护成员,但不能直接访问父类的公有成员或私有成员。
私有继承
class A{
public:
int a;
protected:
int b;
};
class B : protected A{
private:
int a;
int b;
};
私有继承(private inheritance)是C++中一种继承方式。
在私有继承中,子类继承了父类的所有公有成员和保护成员,但将它们都作为自己的私有成员,即对外不可见。
继承的对象模型
父类中的所有属性,子类都会继承下来,只是访问的权限不同。
可以通过VS自带的开发人员工具来看类的模型。
命令:
cd 类的文件夹
cl /d1 reportSingleClassLayout(ClassName) (ClaaFile.cpp)
构造和析构的顺序
一个原则:谁是父类谁先构造,谁是子类谁先析构。
子类中的同名成员
如果在子类中有与父类中存在一个同名的成员,那么编译器会怎样选择成员呢?
如果直接用.
运算符来进行访问,编译器就会用子类中的成员
想要访问父类中的同名成员,就要用::
域运算符来指定域。
注意:如果子类中出现了与父类中的同名函数,子类会自动的隐藏父类中的所有同名函数,这时候想要访问父类中的同名函数 ,只能用::
域运算符。
多继承
C++支持多继承的方式,但是不建议使用,可以会出现同名函数的混乱问题,所以最好不要认两个爹。
Class Son : public Base1, public Base2{};
菱形继承
菱形继承,又称钻石继承,是多继承的一种实例。
class Animal { // 基类 Animal
public:
void eat() {
cout << "动物正在进食" << endl;
}
};
class Cat : public Animal { // 派生类 Cat 继承自 Animal
public:
void meow() {
cout << "猫在喵喵叫" << endl;
}
};
class Dog : public Animal { // 派生类 Dog 继承自 Animal
public:
void bark() {
cout << "狗在汪汪叫" << endl;
}
};
class Pet : public Cat, public Dog { // 多重继承,继承自 Cat 和 Dog
};
int main() {
Pet pet;
pet.eat(); // 方法存在二义性,编译错误
return 0;
}
菱形继承引入了一个二义性问题,编译器无法确定在访问共享基类成员时应该选择哪个继承路径。
比如:Pet
类对象无法直接调用 eat()
方法,因为存在二义性。编译器无法判断应该从 Cat
还是 Dog
继承的 eat()
方法。
为了解决菱形继承带来的问题,可以使用虚继承(virtual inheritance)
。通过在共享基类前面使用 virtual
关键字,可以确保只有一份共享基类的实例。修改上面的示例
class Animal { // 基类 Animal
public:
void eat() {
cout << "动物正在进食" << endl;
}
};
class Cat : public virtual Animal { // 派生类 Cat 继承自 Animal,虚继承
public:
void meow() {
cout << "猫在喵喵叫" << endl;
}
};
class Dog : public virtual Animal { // 派生类 Dog 继承自 Animal,虚继承
public:
void bark() {
cout << "狗在汪汪叫" << endl;
}
};
class Pet : public Cat, public Dog { // 多重继承,继承自 Cat 和 Dog
};
int main() {
Pet pet;
pet.eat(); // 正常调用共享基类的成员函数
return 0;
}