C ++静态成员函数重载继承
c++ static member function overloading with inheritance
我有以下代码:
struct CommonVariables
{/*some common variables that need to be proceed*/};
struct CommonHandler
{
static void foo(const CommonVariables& vars) {/*processed vars*/}
void bar(const CommonVariables& vars) {/*processed vars*/}
};
struct AnotherVariables
{/*another variables*/};
struct AnotherHandler
{
static void foo(const AnotherVariables& vars) {/*processed vars*/}
void bar(const AnotherVariables& vars) {/*processed vars*/}
};
struct Derived : CommonHandler, AnotherHandler
{};
当我尝试调用 Derived::foo(/any variable type/) 或 Derived d; d.bar(/任意变量类型/),编译器报错:"reference to 'foo(or bar)' is ambiguous".
然而下面我的情况几乎一样:
struct DifferentHandler
{
static void foo(const CommonVariables& vars) {}
static void foo(const AnotherVariables& vars) {}
void bar(const AnotherVariables& vars) {}
void bar(const CommonVariables& vars) {}
};
并且调用 DifferentHandler::foo(/任何变量类型/) 或 'bar' 工作得很好。
有很多解决方案可以解决第一个代码块(template traits,等等)。我特别想要的是通过继承来重载方法。而且我不明白为什么来自 Derived 的调用不明确(因为输入参数有不同的类型,从编译器的角度来看这些函数是不同的。就像在 DifferentHandler 中一样)
注意:我已经尝试过 MinGW5.8(在 Qt Creator 中)和 MSVC2015 在 VS2015 中。两个编译器都产生相同的错误。
给你:
struct Derived : CommonHandler, AnotherHandler
{
using CommonHandler::foo;
using CommonHandler::bar;
using AnotherHandler::foo;
using AnotherHandler::bar;
};
解决了您的问题。
原始代码无法运行的原因在C++标准中找到。以下是有趣的引述:
10 月 2 日:
The base class members are said to be inherited by the derived class.
Inherited members can be referred to in expressions in the same manner
as other members of the derived class, unless their names are hidden
or ambiguous (10.2).
继续阅读到 10.2:
Member name lookup determines the meaning of a name (id-expression) in
a class scope (3.3.7). Name lookup can result in an ambiguity, in
which case the program is ill-formed....
...consists of two component sets: the declaration set, a
set of members named f...
If the name of an overloaded function is unambiguously found, overloading resolution (13.3) also takes place before access control
基本上,它首先按名称进行,然后再应用解析。通过 using
声明将它们引入派生 class 将它们全部置于派生 class 的范围内,其中正常解析规则启动。
在 C++ 中,如果派生 class 的成员函数与基类 class 的成员函数同名,则派生 class 的版本 隐藏 基本版本——即使函数签名不同,否则您会期望它们过载。 (如果基础 class 成员函数是虚拟的,那么派生的 class 的签名必须完全匹配*,否则它将(通常是无意地)隐藏基础 class 的版本——这就是 C++11 添加 override
伪关键字的原因。
例如:
struct base {
void foo(std::string s) {}
};
struct derived : base {
void foo(int i) {}
};
int main() {
derived d;
d.foo("hello"); // Error -- cannot convert const char* to int
}
解决方案是使用 using
指令将基 class 的成员函数带入派生的 class 作用域,即
struct derived : base {
using base::foo;
void foo(int i) {}
};
(另一种方法是使用晦涩难懂的
derived d;
d.base::foo("hello"); // works
指定要调用基本 class 版本的语法,但这在现实世界中很少见。)
我有以下代码:
struct CommonVariables
{/*some common variables that need to be proceed*/};
struct CommonHandler
{
static void foo(const CommonVariables& vars) {/*processed vars*/}
void bar(const CommonVariables& vars) {/*processed vars*/}
};
struct AnotherVariables
{/*another variables*/};
struct AnotherHandler
{
static void foo(const AnotherVariables& vars) {/*processed vars*/}
void bar(const AnotherVariables& vars) {/*processed vars*/}
};
struct Derived : CommonHandler, AnotherHandler
{};
当我尝试调用 Derived::foo(/any variable type/) 或 Derived d; d.bar(/任意变量类型/),编译器报错:"reference to 'foo(or bar)' is ambiguous".
然而下面我的情况几乎一样:
struct DifferentHandler
{
static void foo(const CommonVariables& vars) {}
static void foo(const AnotherVariables& vars) {}
void bar(const AnotherVariables& vars) {}
void bar(const CommonVariables& vars) {}
};
并且调用 DifferentHandler::foo(/任何变量类型/) 或 'bar' 工作得很好。
有很多解决方案可以解决第一个代码块(template traits,等等)。我特别想要的是通过继承来重载方法。而且我不明白为什么来自 Derived 的调用不明确(因为输入参数有不同的类型,从编译器的角度来看这些函数是不同的。就像在 DifferentHandler 中一样)
注意:我已经尝试过 MinGW5.8(在 Qt Creator 中)和 MSVC2015 在 VS2015 中。两个编译器都产生相同的错误。
给你:
struct Derived : CommonHandler, AnotherHandler
{
using CommonHandler::foo;
using CommonHandler::bar;
using AnotherHandler::foo;
using AnotherHandler::bar;
};
解决了您的问题。
原始代码无法运行的原因在C++标准中找到。以下是有趣的引述:
10 月 2 日:
The base class members are said to be inherited by the derived class. Inherited members can be referred to in expressions in the same manner as other members of the derived class, unless their names are hidden or ambiguous (10.2).
继续阅读到 10.2:
Member name lookup determines the meaning of a name (id-expression) in a class scope (3.3.7). Name lookup can result in an ambiguity, in which case the program is ill-formed....
...consists of two component sets: the declaration set, a set of members named f...
If the name of an overloaded function is unambiguously found, overloading resolution (13.3) also takes place before access control
基本上,它首先按名称进行,然后再应用解析。通过 using
声明将它们引入派生 class 将它们全部置于派生 class 的范围内,其中正常解析规则启动。
在 C++ 中,如果派生 class 的成员函数与基类 class 的成员函数同名,则派生 class 的版本 隐藏 基本版本——即使函数签名不同,否则您会期望它们过载。 (如果基础 class 成员函数是虚拟的,那么派生的 class 的签名必须完全匹配*,否则它将(通常是无意地)隐藏基础 class 的版本——这就是 C++11 添加 override
伪关键字的原因。
例如:
struct base {
void foo(std::string s) {}
};
struct derived : base {
void foo(int i) {}
};
int main() {
derived d;
d.foo("hello"); // Error -- cannot convert const char* to int
}
解决方案是使用 using
指令将基 class 的成员函数带入派生的 class 作用域,即
struct derived : base {
using base::foo;
void foo(int i) {}
};
(另一种方法是使用晦涩难懂的
derived d;
d.base::foo("hello"); // works
指定要调用基本 class 版本的语法,但这在现实世界中很少见。)