多态在运行和编译两个方面当中c++代码示例
以下是运行方面的,通过虚函数和对象的指针和引用实现,通过虚函数和继承实现多态
#include <iostream>
// 基类
class Shape {
public:
virtual void draw() {
std::cout << "绘制形状" << std::endl;
}
};
// 派生类1
class Circle : public Shape {
public:
void draw() override {
std::cout << "绘制圆形" << std::endl;
}
};
// 派生类2
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "绘制矩形" << std::endl;
}
};
int main() {
Shape* shape1 = new Circle(); // 使用基类指针指向派生类对象
Shape* shape2 = new Rectangle(); // 使用基类指针指向派生类对象
shape1->draw(); // 调用派生类的重写函数
shape2->draw(); // 调用派生类的重写函数
delete shape1;
delete shape2;
return 0;
}
在编译方面的多态性,主要表现在函数重载和计算符的重载
这个是函数重载方面的多态性
void print(int num) {
std::cout << "整数: " << num << std::endl;
}
void print(double num) {
std::cout << "浮点数: " << num << std::endl;
}
print(10); // 调用print(int)函数
print(3.14); // 调用print(double)函数
这个是计算符号方面的多态性
class Vector {
private:
double x, y;
public:
Vector(double x, double y) : x(x), y(y) {}
Vector operator+(const Vector& other) {
return Vector(x + other.x, y + other.y);
}
};
Vector v1(1.0, 2.0);
Vector v2(3.0, 4.0);
Vector v3 = v1 + v2; // 通过运算符+重载实现向量的相加
虚函数
虚函数是在基类中声明为虚拟的成员函数,它在派生类中可以被重写,用于实现运行时多态性。
虚表和虚函数的关系以及虚表实现原理
虚表(Virtual Table)是一个指针数组,用于存储指向虚函数的指针。它是一种用于实现动态多态性的数据结构
虚表是在编译时静态生成的,与类的定义关联。对于每个包含虚函数的类,编译器会生成一个对应的虚表。
虚表中的每个元素(指针)对应于类中的一个虚函数,按照它们在类中声明的顺序排列。通过这些指针,可以在运行时动态地确定并调用正确的虚函数实现。
虚表的指针数组通常存储在类的元数据中。每个对象在其内存布局中通常会包含一个指向其所属类的虚表的指针(虚指针或vptr),它指向类的虚表。
纯虚函数的作用
1、实现接口定义:纯虚函数用于定义基类的接口,它指定了派生类需要实现的函数接口。基类通过声明纯虚函数,定义了一个规范或契约,要求派生类提供相应的实现。
2、强制派生类实现:通过声明纯虚函数,基类可以要求所有的派生类必须提供对应的实现。如果派生类没有实现纯虚函数,那么该派生类也会成为抽象类,无法实例化。
3、实现多态性:纯虚函数可以作为多态性的一部分。通过基类的指针或引用调用纯虚函数,可以根据实际的对象类型,调用相应的派生类实现,实现运行时多态性。
4、提供默认实现:纯虚函数也可以提供默认实现。在基类中,可以为纯虚函数提供一个默认的实现,派生类可以选择是否覆盖该默认实现。