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.
- performance-critical 函数应该是虚函数吗?
- 你真的测量过速度吗?有明显的延迟吗?还是电脑太快了?
我有一个派生的 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.
- performance-critical 函数应该是虚函数吗?
- 你真的测量过速度吗?有明显的延迟吗?还是电脑太快了?