【问题标题】:c++ static member function overloading with inheritancec++静态成员函数重载继承
【发布时间】:2017-04-24 19:44:29
【问题描述】:

我有以下代码:

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(/任何变量类型/),编译器给我一个错误:“对 'foo(or bar)' 的引用不明确”。

但下面我的情况几乎相同:

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(/any variable type/) 或 'bar' 就可以了。

有很多解决方案可以解决第一个代码块(template traits 等)。我特别想要的是通过继承重载方法。而且我不明白为什么来自 Derived 的调用是模棱两可的(因为输入参数有不同的类型,从编译器的角度来看,这些函数是不同的。就像在 DifferentHandler 中一样)

注意:我在 VS2015 中尝试过 MinGW5.8(在 Qt Creator 中)和 MSVC2015。两个编译器都产生了同样的错误。

【问题讨论】:

  • 重复:stackoverflow.com/questions/5365689/… 我不知道如何或没有权限将其标记为这样。
  • @ChristopherPisz,那是您链接的帖子的副本吗?我看不出有什么相似之处。
  • 为什么这个问题被否决了?哪些人不喜欢它?

标签: c++ inheritance static-methods


【解决方案1】:

给你:

struct Derived : CommonHandler, AnotherHandler
{
    using CommonHandler::foo;
    using CommonHandler::bar;
    using AnotherHandler::foo;
    using AnotherHandler::bar;
};

解决您的问题。

原始代码不起作用的原因在 C++ 标准中找到。以下是有趣的引语:

10 月 2 日:

基类成员被称为由派生类继承。 继承的成员可以以相同的方式在表达式中引用 作为派生类的其他成员,除非他们的名字被隐藏 或模棱两可 (10.2)。

继续阅读到 10.2:

成员名称查找确定名称(id-expression)在 类范围(3.3.7)。名称查找可能会导致歧义,在 在这种情况下程序格式不正确....

...由两个组件集组成:声明集、a 一组成员命名 f...

如果明确找到重载函数的名称,则重载决议 (13.3) 也发生在访问控制之前

基本上,它先按名称,然后再应用解析。通过using 声明将它们引入派生类,将它们全部放在派生类的范围内,正常解析规则在此起作用。

【讨论】:

  • 你能解释一下问题到底是什么以及为什么能解决这个问题吗?是不是在原始代码中,编译器只先按名称搜索(而不是按完整原型),而不能决定先查看 CommonHandler 或 AnotherHandler ?还是别的什么?
【解决方案2】:

在 C++ 中,如果派生类的成员函数与基类的成员函数同名,则派生类的版本隐藏基版本 -- 即使函数签名是不同的,否则您会期望它们超载。 (如果基类成员函数是虚拟的,那么派生类的签名必须完全匹配*,否则它会(通常无意)隐藏基类的版本——这就是 C++11 添加override psuedo-keyword 的原因)。

例如:

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指令将基类的成员函数带入派生类作用域,即

struct derived : base {
    using base::foo;
    void foo(int i) {}
};

(另一种方法是使用晦涩的

derived d;
d.base::foo("hello"); // works

指定要调用基类版本的语法,但这在现实世界中很少见。)

【讨论】:

  • 感谢您的简化说明!
猜你喜欢
  • 2013-05-09
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
相关资源
最近更新 更多