example:
#include <iostream>
class B
{
public:
virtual void bar();
virtual void qux();
};
void B::bar()
{
std::cout << "This is B's implementation of bar" << std::endl;
}
void B::qux()
{
std::cout << "This is B's implementation of qux" << std::endl;
}
class C : public B
{
public:
void bar() override;
};
void C::bar()
{
std::cout << "This is C's implementation of bar" << std::endl;
}
Main:
B* b = new C();
b->bar();
虚函数表:
实际的执行过程是:b是一个class C类型的指针,则它使用C的vpointer来寻找虚函数表,也就是C的虚函数表,其中bar()的函数指针是C::bar(),所以执行结果是"This is C's implementation of bar"
。
如果这些同名函数都没有virtual关键字,则都会调用基类的函数。
当基类和派生类有同名函数,但没有virtual关键字时,没有重写发生:
// SameNameFunctionTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class Base {
public:
void test() {
cout << "Base Test" << endl;
}
};
class Derived : public Base {
public:
void test() {
cout << "Derived Test" << endl;
}
};
int main()
{
Derived* d = new Derived();
d->test();
Base* b = new Derived();
b->test();
return 0;
}
Output:
Derived Test
Base Test
此时完全取决于调用函数的是基类还是派生类,基类就调用基类的函数。
另一个例子:
#include <iostream>
#include <string>
using namespace std;
struct B {
virtual void f() const {
cout << "B::f" << endl;
}
void g() const {
cout << "B::g" << endl;
}
};
struct D : B {
void f() const override {
cout << "D::f" << endl;
}
void g(){
cout << "D::g" << endl;
}
};
struct DD : D {
void f(){
cout << "DD::f" << endl;
}
void g() const {
cout << "DD:g" << endl;
}
};
void call(const B &b) {
b.f();
b.g();
}
int main(int argc, char **argv) {
B b;
D d;
DD dd;
call(b);
call(d);
call(dd);
b.f();
b.g();
d.f();
d.g();
dd.f();
dd.g();
return 0;
}
output:
B::f
B::g
D::f
B::g
D::f
B::g // call(dd) 中的 b.g(),g()不是虚函数,调用基类或者子类的函数完全由显式的对象是什么类型决定的,这里是b类型,所以B::g()被调用
B::f
B::g
D::f
D::g
DD::f
DD:g
另一个问题是如果父类中的函数调用了一个虚函数,这个虚函数同时存在于子类和父类中,那么该调用哪个函数呢?
#include <iostream>
#include <string>
using namespace std;
class Base {
public:
virtual void f() {
cout << "call base f()" << endl;
g();
}
virtual void g() {
cout << "call base g()" << endl;
}
};
class Derived : public Base {
public:
virtual void f() {
cout << "call derived f()" << endl;
Base::f();
}
virtual void g() {
cout << "call derived g()" << endl;
}
};
int main(int argc, char **argv) {
Base *b = new Derived();
b->f();
return 0;
}
output:
call derived f()
call base f()
call derived g()
实际上调用了子函数中的虚函数,因为调用的对象是一个子类对象,可以理解为this指针指向一个子类对象,因此它在多态时,看到的都是子类虚函数表中的的虚函数。