Derived class 不会覆盖具有不同签名的虚函数

Derived class doesn't override a virtual function with a different signature

我有一个派生的 class,我希望其中一个函数覆盖其在基础 class 中的版本,但具有不同的签名。 简单示例:

#include "stdio.h"

bool use_foo = false;

class Foo {
public:
    virtual int func(double x) { printf ("%f in Foo!\n", x); }
};

class Bar : public Foo {
public:
    int func(short x) { printf ("%d in Bar!\n", x); }
};

int main () {
    Foo* A;
    if (use_foo) 
        A = new Foo;
    else 
        A = new Bar;

    A->func(2);
    return 0;
}

即使 A 被分配为派生 class:

,上述代码仍将调用基础 class 副本
> g++ test.cpp -o test -O3 && ./test
2.000000 in Foo!

因为(据我所知)参数可以转换为匹配基础 class 签名,并且派生的 class 不会因为这种差异而覆盖它(但不会在那种情况下,它隐藏吗?)。如果我将基础 class 函数更改为也将 short 作为参数,派生的 class 确实会覆盖它。

有没有一种简单的方法可以说服调用使用基于指针的正确函数?我可以像这样添加另一个函数:

class Bar : public Foo {
public:
    int func2(short x) { printf ("%d in Bar!\n", x); }
    int func(double x) { func2(x); }
};

但是我会一直转换参数(short->double->short),这个函数对性能很关键。有没有更好的方法?

这些函数签名不相同:

virtual int func(double x) {...} // base class
int func(short x) {...} // derived class

一个使用double参数,另一个使用short。要使 overriding 发生,必须满足几个条件。 相同 基本函数和派生函数的参数类型是其中之一。 Bellow 是 Scott Meyers 关于所有要求的 "Modern Effective C++" 书中的摘录:

• The base class function must be virtual.

• The base and derived function names must be identical (except in the case of destructors).

• The parameter types of the base and derived functions must be identical.

• The constness of the base and derived functions must be identical.

• The return types and exception specifications of the base and derived functions must be compatible.

或者,使签名相同并在派生函数体内执行转换:

int func(double x) override {
    short temp = static_cast<short>(x);
    // ...
}

这有什么意义呢?使用虚函数的原因是调用者只需要知道基础 class,因此只需要知道 base-class 签名。

换句话说,具有 Foo&Foo*std::unique_ptr<Foo> 的代码无论如何只知道函数的 double 版本.它会在调用 func 时传递一个 double,因为它还应该做什么?

也许您真正想要做的是将 double 转换为 short 的函数的 subclass 实现。这是一个例子,它也摆脱了 printf 以支持 type-safe C++ 流:

class Bar : public Foo {
public:
    int func(double x) { std::cout << static_cast<short>(x) << " in Bar!\n"; }
};

请注意,自 C++11 起,我们鼓励您使用 override 标记重写函数。

and this function is performance critical.

  1. performance-critical 函数应该是虚函数吗?
  2. 你真的测量过速度吗?有明显的延迟吗?还是电脑太快了?