多态的实现依赖于虚函数。类存在虚函数,则编译器会为每个类创建虚函数表。
虚函数的调用过程:创建基类赋值给基类指针 --> 虚函数表指针 --> 虚函数表(数组) 里面进行查询并调用实际的函数。
基本实现
#include <iostream>
// 基类
class Base {
public:
// 虚函数1
virtual void func1() { std::cout << "Base::func1()" << std::endl; }
// 虚函数2
virtual void func2() { std::cout << "Base::func2()" << std::endl; }
};
// 派生类 继承
class Derived : public Base {
public:
// 重写
void func1() override { std::cout << "Derived::func1()" << std::endl; }
};
int main() {
Base* ptr = new Derived();
// 通过基类指针调用虚函数,运行时动态绑定
ptr->func1(); // 输出: Derived::func1()
ptr->func2(); // 输出: Base::func2()
delete ptr;
return 0;
}
多重继承
派生类继承了多个基类,那就存在多个虚函数指针。
#include <iostream>
// 基类A
class BaseA {
public:
virtual void funcA() { std::cout << "BaseA::funcA()" << std::endl; }
virtual void common() { std::cout << "BaseA::common()" << std::endl; }
};
// 基类B
class BaseB {
public:
virtual void funcB() { std::cout << "BaseB::funcB()" << std::endl; }
virtual void common() { std::cout << "BaseB::common()" << std::endl; }
};
// 派生类:多重继承自BaseA和BaseB
class Derived : public BaseA, public BaseB {
public:
void funcA() override { std::cout << "Derived::funcA()" << std::endl; }
void funcB() override { std::cout << "Derived::funcB()" << std::endl; }
void common() override { std::cout << "Derived::common()" << std::endl; }
};
int main() {
Derived d;
// 通过不同基类指针调用虚函数
BaseA* ptrA = &d;
BaseB* ptrB = &d;
ptrA->funcA(); // 输出: Derived::funcA()
ptrA->common(); // 输出: Derived::common()
ptrB->funcB(); // 输出: Derived::funcB()
ptrB->common(); // 输出: Derived::common()
// 直接通过派生类对象调用
d.funcA(); // 输出: Derived::funcA()
d.funcB(); // 输出: Derived::funcB()
d.common(); // 输出: Derived::common()
return 0;
}
菱形继承
继承关系:
A
/
B C
\ /
D
虚基表
当前例子:D里面会有B和C的虚函数表,当调用公共的虚函数时,会进行进行跳转。
#include <iostream>
class A {
public:
virtual void foo() { std::cout << "A::foo()" << std::endl; }
};
class B : virtual public A {
public:
void foo() override { std::cout << "B::foo()" << std::endl; }
};
class C : virtual public A {
public:
void foo() override { std::cout << "C::foo()" << std::endl; }
};
class D : public B, public C {
public:
void foo() override { std::cout << "D::foo()" << std::endl; }
};
int main() {
D d;
A* ptr = &d;
ptr->foo(); // 输出: D::foo()
return 0;
}