2

What's the difference between redefining and using a virtual function? Don't they serve the same purpose? You are allowing objects of a derived class to call their own versions of a function by the same name in both cases..so where is the distinction?

4

3 回答 3

5

一个例子说得最好:

#include <iostream>

using namespace std;

class A {
public:
  virtual void f1() { cout << "Class A" << endl; }
  void f2() { cout << "Class A" << endl; }
  virtual ~A(){}
};

class B : public A {
public:
  virtual void f1() { cout << "Class B" << endl; }
  void f2() { cout << "Class B" << endl; }
  virtual ~B(){}
};

int main()
{
  A *a = new B;
  a->f1();
  a->f2();
}

...

$ ./override 
Class B
Class A

可以看到,当我们引用 B 的实例时,f1()仍然调用B's 的版本,但是f2()调用了A's。

当你声明一个函数 virtual 时,你是说当我们调用它时,我们应该使用 vtable 来查找要调用的函数的正确版本,因此即使你引用了函数,你总是会得到该函数的派生版本。它作为祖先类型。如果没有 virtual,它只会使用您引用它的类型中的定义。

于 2013-03-20T03:32:47.923 回答
3

区别在于当您有对基类的引用或指针时。对虚函数的调用将调用最派生版本,而对普通函数的调用将调用基类版本。

如果您直接使用变量或指向最派生类的引用或指针,则没有实际区别。

于 2013-03-20T03:29:56.063 回答
2

TL;博士

在 C++ 中利用多态性的唯一方法是通过虚函数和指针(和引用)。virtual 关键字将告诉编译器在处理指向具有子类的动态类型的基类的指针时决定调用哪个版本的虚函数时,分配一个虚函数表到哪里查看。

多态性如何在 C++ 中工作

我们举一个简单的例子:

class A { public: virtual void eat() { std::cout << "Class A" << std::endl; }
class B : public A {};
class C : public B { virtual void eat() { std::cout << "Class C" << std::endl; }

注意:第一个函数/方法定义后可以省略 virtual 关键字。

以下:

A a; B b; C c;
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
ptrA->eat();
ptrB->eat();
ptrC->eat();

将打印:

Class A
Class A
Class C

如果我们没有将函数声明为eatvirtual,那么输出将是:

Class A
Class A
Class A
于 2013-03-20T03:40:30.543 回答