【问题标题】:Override virtual function of base classes, which do not share common interface覆盖不共享通用接口的基类的虚函数
【发布时间】:2012-07-12 15:42:00
【问题描述】:
#include <iostream>
struct B1
{
    virtual void method()=0;
    virtual ~B1(){}
};

struct B2
{
    virtual void method()=0;
    virtual ~B2(){}
};

struct D: B1, B2
{
    virtual void method()
    {
        std::cout << "D::method\n";
    };
};

int main(int argc,char *argv[])
{
    D d;
    B1 &b1=d;
    B2 &b2=d;
    b1.method();
    b2.method();
    return 0;
}

注意,B1 和 B2 不共享公共接口。

这合法吗?如果是 - 在哪个标准中? C++98/03/11 ?

msvc和gcc都编译OK了。

以前我认为,我必须为这种情况使用一些通用接口(可能的虚拟继承)。

这种情况有什么特别的名字吗?

请详细说明它是如何工作的?也许是一些 ISO 参考资料?

【问题讨论】:

  • 如果您解释是什么导致您认为这是一个特殊情况,那么有人可能会找到一个很好的解释。
  • 因为在这种情况下,我希望在 D: B1::method 和 B2::method 中有两个不同的独立继承虚函数。

标签: c++ overriding virtual multiple-inheritance


【解决方案1】:

您的代码格式正确:void D::method() 覆盖 void B1::method()void B2::method()

规范声明(C++11 §10.3/2):

如果一个虚成员函数vf在类Base和类Derived中声明,直接或间接派生自Base,则成员函数vf同名,参数类型-list、cv-qualification 和 ref-qualifier(或不存在相同)作为声明 Base::vf,然后 Derived::vf 也是虚拟的(无论是否如此声明)并覆盖 Base::vf

B1 声明了一个虚成员函数void B1::method()D 类派生自 B1,它还声明了一个具有相同名称 (method)、相同参数列表(无参数)、相同 cv-qualification(无限定)和相同引用的成员函数限定符(无限定)。

因此,void D::method() 会覆盖 void B1::method()

同样的逻辑适用于void B2::method()(只需将B2 替换为上述说明中的B1),因此void D::method() 会覆盖void B1::method()void B2::method()

【讨论】:

  • 谢谢,听起来不错。我在 C++03 和 C++98 上找到了类似的项目。但是,我很好奇,这种情况是否有一些标准补充?多继承的一些特殊说明?
  • 除了“and ref-qualifier”之外,我希望 C++98 和 C++03 中的规范是相同的。
  • 太好了,很高兴知道。顺便说一句,如果通过基类引用/指针访问 D,则仅 使用 method() 只允许 D 使用它。比较stackoverflow.com/questions/3310910/…
  • 您的解释很有道理,但仍然令人惊讶。同一段代码同时实现了两种不同的方法,因为 B1::method 和 B2::method 肯定是不相关的。
  • 如果我在 C++ 中学到的每件令人惊讶的事情都能得到一美元...好吧,我会有很多美元。
【解决方案2】:

afaik 这在每个标准中都是合法的。我不确定它是否有自己的特殊名称,但它类似于diamond problem

如果您在 D 中重写“virtual void method()”,那么您将同时重写 B1 和 B2 中的方法。

编辑:

回答为什么您没有“D: B1::method 和 B2::method 中两个不同的独立继承虚函数”:

在重写方法时,只能指定函数名、返回类型和参数,但不能在重写时添加关于继承自哪个方法的签名细节。

想象一下它是可能的,那么它可能看起来像这样:

struct D: B1, B2
{
    virtual void B1::method()
    {
        std::cout << "D::method\n";
    };
    virtual void B2::method()
    {
        std::cout << "D::method\n";
    };
};

但是看到这里,已经可以说不可能有这样的东西了,因为调用的时候

objectD.method()

你不能指定你正在呼叫哪一个。所以即使有办法重载两者,仍然存在函数调用上的区分问题。

编辑: “无法指定您呼叫的是哪一个。”指的是,您无法指定是要调用 B2::method 的 D 类重载还是 B2 方法本身。 objectD.B2::method 将始终调用 B2(未重载)方法(在这种情况下不会编译,因为 B2 没有实现)

【讨论】:

  • 谢谢,我明白了。我想知道更多细节,因为这让我有点惊讶。
  • @James McNellis 这不是只有在班级成员内部才有可能吗?无效 B1method(){ B1::method } ?
  • 我明白了。不管重载如何,它们仍然调用基类函数。
  • "想象一下它是可能的,那么它可能看起来像这样:" 然后你会得到一个名为 B1::method 的函数,其限定名称是 D::B1::method !但在 C++ 中,D::B1 表示 B1!当unqualified函数名B1::method时,你就知道有问题了。 “所以即使有办法重载两者,”它不会重载,因为函数有不同的名称:B1::methodB2::method!你可以随心所欲地尝试,我只是认为你不能让这个想法奏效。 (但尝试很有趣。;)
猜你喜欢
  • 1970-01-01
  • 2017-06-08
  • 2017-09-22
  • 2014-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 1970-01-01
相关资源
最近更新 更多