C ++中的函数覆盖在没有“虚拟”的情况下工作

时间:2014-01-12 14:38:56

标签: c++ virtual function-overriding

我有一个包含一些函数的类(没有虚函数),还有两个类公开继承该类。在这两个子类中,我重写了基类的相同功能。

在main(位于同一个文件)中创建所有三个类的对象之后,我使用baseclass对象调用原始函数,并使用derivedclass对象调用覆盖的函数。

我期待所有3个函数调用从基类运行原始函数(因为我没有在代码中的任何地方使用'虚拟')但我实际上得到了每个函数的每个版本函数根据其定义的类别工作(3个不同的版本)。

我有类Base&得出如下:

struct Base
{
   void foo();
};

struct Derived : Base
{
   void foo();
};

在main中:

int main()
{
   Derived d;
   d.foo();
}

如果不使用'虚拟'我认为d.foo()应该运行Base :: foo()。

3 个答案:

答案 0 :(得分:7)

“覆盖”......并且不需要。

struct Base
{
   void foo();
};

struct Derived : Base
{
   void foo();
};

int main()
{
   Derived d;
   d.foo();
}

如果我理解正确,那么你期望执行Base::foo(),因为这些功能不是虚拟的,因此不会覆盖另一个。

但是,在这里,你不需要虚拟调度:继承规则只是声明你将为你运行它的对象的类型获得正确的函数。

当您需要虚拟调度/覆盖时,情况略有不同:当您使用间接时:

int main()
{
   Base* ptr = new Derived();
   ptr->foo();
   delete ptr;
}

在上面的代码段中,结果将是Base::foo()被调用,因为表达式ptr->foo()不知道*ptr 真的 a { {1}}。它只知道Derivedptr

这是添加Base*的地方(在这样做的情况下,使一个函数覆盖另一个)会让魔法发生。

答案 1 :(得分:0)

您无法覆盖非虚拟内容。非虚拟成员函数将根据实例对象的类型静态调度。

答案 2 :(得分:0)

你可以通过使一个函数间接调用一个内联函数来“覆盖”一个函数来作弊。像(C++03

这样的东西
 class Foo;
 typedef int foo_sig_t (Foo&, std::string&);
 class Foo {
    foo_sig_t *funptr;
 public:
    int do_fun(std::string&s) { return funptr(*this,s); }
    Foo (foo_sig_t* fun): funptr(fun) {};
    ~Foo () { funptr= NULL; };
    // etc
 };

 class Bar : public Foo {
    static int barfun(Bar&, std::string& s) { 
       std::cout << s << std::endl;
       return (int) s.size();
    };
  public: 
    Bar () : Foo(reinterpret_cast<foo_sig_t*>)(&barfun)) {};
     // etc...
  };

以后:

  Bar b;
  int x=b.do_fun("hello");

官方说这不会重载虚函数,但看起来非常接近虚拟函数。但是,在我上面的Foo示例中,每个Foo实例都有自己的funptr,它不一定由类共享。但是所有Bar个实例共享指向同一funptr相同 barfun

BTW,使用C++11 lambda anonymous functions(内部实现为closures),这将更简单,更短。

当然,virtual functions通常实际上是通过类似的机制实现的:对象(带有一些virtual个东西)隐含地以隐藏字段开头(可能是“命名为”_vptr)给出vtable(或虚方法表)。