C++ 的继承
继承是面向对象编程的一个核心概念,C++ 提供了强大的继承机制,用于描述类之间的层次关系。通过继承,一个类可以基于已有的类创建新类,从而实现代码的复用、扩展和多态性。
1. 基本概念
- 基类(Base Class):被继承的类,也称为父类或超类。
- 派生类(Derived Class):从基类继承来的类,也称为子类。
- 继承的关键字:
class 派生类 : 继承方式 基类
示例:
class Base {
public:
void display() {
cout << "This is Base class" << endl;
}
};
class Derived : public Base {
public:
void show() {
cout << "This is Derived class" << endl;
}
};
int main() {
Derived d;
d.display(); // 调用基类函数
d.show(); // 调用派生类函数
return 0;
}
2. 继承方式
C++ 支持三种继承方式:
(1)Public 继承
- 基类的
public
成员在派生类中仍为public
。 - 基类的
protected
成员在派生类中仍为protected
。 - 基类的
private
成员不会直接继承到派生类。
示例:
class Base {
public:
int x;
protected:
int y;
private:
int z;
};
class Derived : public Base {
public:
void print() {
cout << x << endl; // 可访问 public 成员
cout << y << endl; // 可访问 protected 成员
// cout << z; // 错误,private 成员不可访问
}
};
(2)Protected 继承
- 基类的
public
和protected
成员在派生类中都变为protected
。 - 基类的
private
成员同样不可直接访问。
示例:
class Derived : protected Base {
public:
void print() {
cout << x << endl; // 可访问 public 成员,变为 protected
cout << y << endl; // 可访问 protected 成员
}
};
(3)Private 继承
- 基类的
public
和protected
成员在派生类中都变为private
。 - 基类的
private
成员仍不可直接访问。
示例:
class Derived : private Base {
public:
void print() {
cout << x << endl; // 可访问 public 成员,变为 private
cout << y << endl; // 可访问 protected 成员,变为 private
}
};
3. 构造函数与析构函数
- 构造函数
- 派生类的构造函数不会继承基类的构造函数。
- 如果基类有无参构造函数,派生类的构造函数会隐式调用它。
- 如果基类只有带参数的构造函数,派生类必须显式调用它。
示例:
class Base {
public:
Base(int val) { cout << "Base constructor, val = " << val << endl; }
};
class Derived : public Base {
public:
Derived(int val) : Base(val) { cout << "Derived constructor" << endl; }
};
- 析构函数
- 基类和派生类各自的析构函数会按从派生类到基类的顺序依次调用。
- 如果基类的析构函数不加
virtual
修饰,通过基类指针释放派生类对象时可能出现未完全析构的问题。
示例:
class Base {
public:
virtual ~Base() { cout << "Base destructor" << endl; }
};
class Derived : public Base {
public:
~Derived() { cout << "Derived destructor" << endl; }
};
int main() {
Base* obj = new Derived();
delete obj; // 调用 Derived 和 Base 的析构函数
return 0;
}
4. 多继承
C++ 支持一个类从多个基类继承。
示例:
class Base1 {
public:
void func1() { cout << "Base1" << endl; }
};
class Base2 {
public:
void func2() { cout << "Base2" << endl; }
};
class Derived : public Base1, public Base2 {};
int main() {
Derived obj;
obj.func1();
obj.func2();
return 0;
}
- 菱形继承问题: 当一个类从两个基类继承,而这两个基类又继承自同一个基类时,可能会出现数据和函数重复的问题。
解决方式:虚继承
class Base {
public:
int x;
};
class Base1 : virtual public Base {};
class Base2 : virtual public Base {};
class Derived : public Base1, public Base2 {};
5. 访问控制
- 基类中的成员根据继承方式和访问修饰符,会影响派生类的访问权限。
- 派生类可以通过
protected
或private
来控制基类成员的可访问性。
6. 继承与多态
多态是 C++ 继承的重要特性,通过虚函数实现。
示例:
class Base {
public:
virtual void display() { cout << "Base" << endl; }
};
class Derived : public Base {
public:
void display() override { cout << "Derived" << endl; }
};
int main() {
Base* obj = new Derived();
obj->display(); // 输出 "Derived"
delete obj;
}
我的总结
继承是C++面相对象编程一个重要概念,继承方式有三种public,protect,private会将父类的访问级别改变。
子类不会继承父类的构造函数,父类构造函数如果为无参构造子类构造函数会显示调用它,如果为有参构造,子类构造函数必须显示调用,析构函数如果被继承必须声明为虚函数,否则通过基类指针析构可能会出现不完全析构。
C++支持多重继承,如果出现棱形继承就需要使用虚继承,虚继承通过将基类的实例放置在派生类外部的共享位置,使得派生类只包含一个共享的基类实例,而不是各自独立地包含实例。