【问题标题】:Template Member Function Overloading and Multiple Inheritance in C++C++中的模板成员函数重载和多重继承
【发布时间】:2012-07-27 23:58:55
【问题描述】:

我正在观察以下代码中的行为,我无法轻易解释并希望更好地理解理论。我似乎找不到涵盖这种特殊情况的在线文档来源或现有问题。作为参考,我使用 Visual Studio C++ 2010 编译并运行以下代码:

#include <iostream>
using namespace std;

struct Bottom_Class
{
    template<typename This_Type>
    void Dispatch()
    {
        // A: When this comment is removed, the program does not compile
        //    citing an ambiguous call to Print_Hello
        // ((This_Type*)this)->Print_Hello();

        // B: When this comment is removed instead, the program compiles and
        //    generates the following output:
        //    >> "Goodbye from Top Class!"
        // ((This_Type*)this)->Print_Goodbye<void>();
    }

    void Print_Hello() {cout << "Hello from Bottom Class!" << endl;}

    template<typename This_Type>
    void Print_Goodbye() {cout << "Goodbye from Bottom Class!" << endl;}
};

struct Top_Class
{
    void Print_Hello() {cout << "Hello from Top Class!" << endl;}

    template<typename This_Type>
    void Print_Goodbye() {cout << "Goodbye from Top Class!" << endl;}
};

template<typename Top_Type,typename Bottom_Type>
struct Merged_Class : public Top_Type, public Bottom_Type {};

typedef Merged_Class<Top_Class,Bottom_Class> My_Merged_Class;

void main()
{
    My_Merged_Class my_merged_object;

    my_merged_object.Dispatch<My_Merged_Class>();
}

为什么模板化成员函数与非模板化成员函数的情况不同?

编译器如何决定(在模板化的情况下)Top_Class::Print_Goodbye() 是适当的重载而不是 Bottom_Class::Print_Goodbye()?

提前感谢您的考虑。

【问题讨论】:

  • 如果你把Dispatch()设为全局函数,你还会看到这个问题吗?

标签: c++ visual-studio-2010 templates multiple-inheritance name-lookup


【解决方案1】:

两个 cmets(AFAIK 正确)使用 GCC 4.6.3 生成编译错误。可能是 Microsoft 编译器做错了什么。

➜  scratch  g++ -O2 templ.cc
templ.cc: In member function ‘void Bottom_Class::Dispatch() [with This_Type = Merged_Class<Top_Class, Bottom_Class>]’:
templ.cc:42:48:   instantiated from here
templ.cc:16:9: error: request for member ‘Print_Goodbye’ is ambiguous
templ.cc:22:10: error: candidates are: template<class This_Type> void Bottom_Class::Print_Goodbye()
templ.cc:30:10: error:                 template<class This_Type> void Top_Class::Print_Goodbye()

【讨论】:

  • 这不是一个正确的答案,应该是评论。
  • 怎么样? OP问为什么一个有效而另一个无效。理想情况下,两者都不应该工作 - 这是正确的行为。所以答案可能是它是一个编译器问题,如图所示。没有?
  • 您只是在确认它有效/无效。你没有回答为什么可能有问题。
  • OP 询问为什么编译器会发现一个模棱两可而不是另一个。这意味着他/她了解编译器无法派生要调用的方法。但他/她发现,在一种情况下,编译器能够选择一种方法来调用。正确的行为是编译器拒绝两者 - 我使用 GCC 演示了这一点。我不明白这怎么不能回答 OPs 的问题——我什至暗示这可能与微软的编译器行为不正确有关!
  • @JoachimPileborg "你没有回答为什么会出现问题。" 为什么会出现问题非常清楚:固有这里的歧义:两个(模板)成员函数具有完全相同的签名;这两个类是(或看起来?)对称。除非 parry 和 OP 遗漏了一些微妙的东西,允许编译器打破两个类之间的对称性,否则这是一个正确的答案。即使 parry 遗漏了一些东西并且在这里出错了,它也是一个格式正确的错误答案:它回答了问题,但不正确。
【解决方案2】:

Dispatch 方法中,This_TypeMy_Merged_Class 相同。 My_Merged_Class两个 方法,名称为Print_Hello,当然编译器在区分它们时会有问题。

Dispatch 中对Print_Hello 的调用,在模板替换后,如下所示:

((My_Merged_Class*)this)->Print_Hello();

我希望上述替换可以帮助您更好地了解为什么存在歧义。 Print_Goodbye 实际上应该会出现同样的问题,但它可能是您正在使用的编译器中的一个错误导致它通过。

【讨论】:

  • 哇,这么快的反应。似乎每个人都同意这是一个特定于 MSVC 的错误,我想我可以向 Microsoft 报告。我希望我可以检查两个答案,因为两者都有帮助,但我正在检查这个答案,因为它更清楚地解释了为什么它很可能是编译器错误。出于好奇,有人能复制我的观察吗?
猜你喜欢
  • 1970-01-01
  • 2014-11-11
  • 2020-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 2023-01-15
相关资源
最近更新 更多