在 C++的编程世界中,继承与多态是两个至关重要的概念,它们为代码的组织、复用和灵活性提供了强大的支持。
一、继承的基本概念
1. 私有成员的不可访问性:在父类中定义为私有的成员,子类无法直接使用。尽管子类知道有这些成员的存在,但访问权限限制了其操作。
2. 赋值兼容转换:子类对象可以赋值给父类对象,但父类对象不能赋值给子类对象,这是由于子类可能包含父类所没有的额外信息。
3. 构造函数的调用顺序:子类默认生成的构造函数会自动调用父类的默认构造函数。这确保了在创建子类对象时,先初始化父类的成员。
4. 析构函数的特性:析构函数由于多态的原因,名称会统一处理为 destructor 。子类的析构函数不能被显式调用,它会在子类的析构过程结束后自动被调用。并且,析构的顺序必须是先子后父,因为子类析构时可能会用到父类的成员;而构造的顺序则是先父后子,因为子类可能依赖父类的成员进行初始化。
二、继承的类型
1. 单继承:一个子类只有一个直接父类,这是最常见和简单的继承形式。
2. 多继承:一个子类拥有两个及以上的直接父类,这种形式可能会导致一些复杂的问题,如棱形继承带来的数据冗余和二义性。
3. 虚继承:通过 virtual 关键字来解决棱形继承中的问题,避免数据冗余。但在实际开发中,应谨慎使用虚拟菱形继承,优先考虑组合,以保持低耦合。
三、重写与多态
1. 当子类调用父类的函数时,会根据查找规则在父类中查找。重写是指函数的实现被更改,而函数的签名(包括参数列表和返回类型)保持不变。但需要注意的是,重写函数的缺省值仍然是父类中的设定。
2. 多态的实现需要两个条件同时满足:一是虚函数重写,即重写虚函数的实现;二是通过父类指针或引用调用虚函数。
3. 虚函数重写存在两个例外情况:一是协变,即基类和派生类虚函数返回值类型不同;二是析构函数的重写,基类与派生类析构函数的名字不同。
4. 当构成多态时,如果使用父类指针或引用,就可以调用子类重写的虚函数;否则,会调用父类中的原始函数。
四、纯虚函数与抽象类
纯虚函数通过在虚函数后面添加 = 0 来定义。包含纯虚函数或继承了纯虚函数的类被称为抽象类,抽象类不能实例化对象,必须先重写纯虚函数。
下面是一个简单的示例代码,帮助您更好地理解上述概念:
#include <iostream>
// 父类
class Base {
private:
int privateMember;
public:
Base() {
std::cout << "Base constructor" << std::endl;
}
virtual void virtualMethod() {
std::cout << "Base::virtualMethod()" << std::endl;
}
virtual ~Base() {
std::cout << "Base destructor" << std::endl;
}
};
// 子类
class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor" << std::endl;
}
void virtualMethod() override {
std::cout << "Derived::virtualMethod()" << std::endl;
}
~Derived() {
std::cout << "Derived destructor" << std::endl;
}
};
int main() {
Base* ptr = new Derived();
ptr->virtualMethod();
delete ptr;
return 0;
}
在这个示例中,我们展示了继承、虚函数重写和多态的基本用法。
希望通过这篇博客,能让您对 C++中的继承与多态有更清晰的理解和掌握,从而编写出更加高效和灵活的代码。