在C++中,虚函数与多态密切相关,特别是运行时多态(也称为动态多态)。当一个类中定义了虚函数,并且通过基类指针或引用调用该函数时,实际执行的函数版本将根据对象的动态类型在运行时确定。这种机制依赖于虚函数表(vtable)和虚指针(vptr),由编译器在后台自动管理。
虚函数与运行时多态的基本原理
在C++中,运行时多态的实现依赖于以下条件:
- 基类中声明了虚函数(使用
virtual关键字)。 - 派生类重写了该虚函数。
- 通过基类指针或引用调用该虚函数。
例如:
#include <iostream>
class Base {
public:
virtual void func() {
std::cout << "Base::func()" << std::endl;
}
};
class Derived : public Base {
public:
void func() override {
std::cout << "Derived::func()" << std::endl;
}
};
int main() {
Base* ptr = new Derived();
ptr->func(); // 输出: Derived::func()
delete ptr;
return 0;
}
在这里,ptr是一个指向Base类型的指针,但实际指向Derived对象。由于func是虚函数,运行时会根据对象的实际类型调用Derived::func(),这就是运行时多态。
函数参数指针是否“生效”
虚函数的多态行为与函数的参数类型无关,而只与调用该函数的对象的动态类型有关。参数是指针还是其他类型,不会改变运行时多态的机制。
例如,考虑以下代码:
#include <iostream>
class Base {
public:
virtual void func(int* ptr) {
std::cout << "Base::func() with pointer " << ptr << std::endl;
}
};
class Derived : public Base {
public:
void func(int* ptr) override {
std::cout << "Derived::func() with pointer " << ptr << std::endl;
}
};
int main() {
int value = 42;
int* p = &value;
Base* basePtr = new Derived();
basePtr->func(p); // 输出: Derived::func() with pointer <address>
delete basePtr;
return 0;
}
在此例中,func接受一个int*类型的指针参数。调用basePtr->func(p)时,仍然会根据basePtr指向的实际对象类型(Derived)执行Derived::func()。参数p只是被传递给函数,不影响多态的决议过程。
如果参数是指向基类的指针
虚函数的多态性仅适用于调用该函数的对象(即this指针所指向的对象),而不适用于函数参数的类型。例如:
#include <iostream>
class A {
public:
virtual void print() { std::cout << "A" << std::endl; }
};
class B : public A {
public:
void print() override { std::cout << "B" << std::endl; }
};
class Base {
public:
virtual void func(A* a) {
a->print();
std::cout << "Base::func()" << std::endl;
}
};
class Derived : public Base {
public:
void func(A* a) override {
a->print();
std::cout << "Derived::func()" << std::endl;
}
};
int main() {
Base* basePtr = new Derived();
A* aPtr = new B();
basePtr->func(aPtr); // 输出: B 然后 Derived::func()
delete basePtr;
delete aPtr;
return 0;
}
在这里,func的参数a是一个A*类型的指针,指向B对象。调用basePtr->func(aPtr)时:
basePtr的动态类型是Derived,因此调用Derived::func()。- 在
func内部,a->print()根据aPtr的动态类型(B)调用B::print()。
两者的多态行为是独立的:basePtr的多态决定调用哪个func,而aPtr的多态决定调用哪个print。
总结
- 虚函数的运行时多态与函数参数的类型(包括是否为指针)无关,多态仅取决于调用该函数的对象的动态类型。
- 如果参数是指针类型,它会被正常传递给虚函数,但不会影响虚函数本身的决议过程。
- 如果参数本身是指向基类的指针,其自身的多态行为(如调用其虚函数)与调用者的多态行为是分开的。
1266

被折叠的 条评论
为什么被折叠?



