C++之“虚”篇
·
1.虚函数
虚函数是 C++ 中支持 动态多态 的关键机制之一。它允许通过基类的指针或引用调用派生类中的重写函数,而不管指针或引用的类型是什么。虚函数在基类中使用 virtual 关键字声明,并且可以在派生类中进行重写。
#include <iostream>
using namespace std;
class Base {
public:
virtual void show() { // 基类中的虚函数
cout << "Base class show() called." << endl;
}
};
class Derived : public Base {
public:
void show() override { // 派生类重写虚函数
cout << "Derived class show() called." << endl;
}
};
int main() {
Base* basePtr;
Derived derivedObj;
basePtr = &derivedObj;
basePtr->show(); // 输出:Derived class show() called.
return 0;
}
普通虚函数:
-
如果派生类没有重写该函数,它会继承基类的实现。
-
如果派生类重写了该函数,它会覆盖基类的实现。
纯虚函数:
如果基类有纯虚函数,派生类必须提供一个实现,否则派生类也会变成抽象类,不能实例化。
| 特性 | 普通虚函数 | 纯虚函数 |
|---|---|---|
| 定义 | 提供默认实现,派生类可以选择覆盖 | 不提供实现,必须在派生类中实现 |
| 是否可以实例化基类 | 可以实例化基类对象,除非类中有纯虚函数 | 不能实例化基类对象,类为抽象类 |
| 派生类要求 | 派生类可以选择是否重写普通虚函数 | 派生类必须重写纯虚函数,除非派生类本身为抽象类 |
| 多态 | 支持多态,通过基类指针/引用调用派生类实现 | 同样支持多态,但派生类必须实现纯虚函数 |
| 用途 | 用于提供默认行为或接口 | 用于定义接口,强制派生类实现 |
虽然拥有纯虚函数的抽象类无法实例化,但是可以使用指针指向派生类,代码如下:
#include <iostream>
class Shape {
public:
// 纯虚函数,强制派生类必须实现
virtual void draw() = 0;
virtual ~Shape() = default; // 虚析构函数,确保派生类能正确析构
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing Circle" << std::endl;
}
};
class Square : public Shape {
public:
void draw() override {
std::cout << "Drawing Square" << std::endl;
}
};
int main() {
// 使用基类指针指向派生类对象
Shape* shape1 = new Circle(); // 基类指针指向派生类对象
Shape* shape2 = new Square(); // 基类指针指向另一个派生类对象
// 调用派生类的重写方法,发生多态
shape1->draw(); // 输出:Drawing Circle
shape2->draw(); // 输出:Drawing Square
// 清理资源
delete shape1;
delete shape2;
return 0;
}
2.虚继承
虚继承是解决 菱形继承问题 的一种机制。菱形继承问题发生在多重继承中,当一个派生类同时继承两个类的相同基类时,会导致该基类的成员变量和函数被多次继承,形成多余的冗余数据和不必要的复杂性。
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A constructor" << endl; }
void show() { cout << "Class A" << endl; }
};
class B : virtual public A {
public:
B() { cout << "B constructor" << endl; }
};
class C : virtual public A {
public:
C() { cout << "C constructor" << endl; }
};
class D : public B, public C {
public:
D() { cout << "D constructor" << endl; }
};
int main() {
D obj; // 只会调用 A 构造函数一次
obj.show(); // 输出:Class A
return 0;
}
-
虚继承要求虚基类的构造函数只能由最派生类的构造函数调用。
-
这样保证了虚基类的构造只会执行一次,避免了重复构造的问题。
3.虚基类
虚基类是虚继承的基础。当一个类通过虚继承继承另一个类时,继承的那个类就被称为虚基类。虚基类确保在继承层次结构中,基类对象只有一份。
4.虚类
#include <iostream>
class Shape {
public:
// 纯虚函数
virtual void draw() = 0;
// 析构函数通常也会被声明为虚函数
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing Circle" << std::endl;
}
};
class Square : public Shape {
public:
void draw() override {
std::cout << "Drawing Square" << std::endl;
}
};
int main() {
// Shape s; // 错误:不能实例化抽象类
Shape* shape = new Circle();
shape->draw(); // 输出:Drawing Circle
delete shape;
shape = new Square();
shape->draw(); // 输出:Drawing Square
delete shape;
return 0;
}
更多推荐



所有评论(0)