【问题标题】:c++ emulation of the "super" keyword“super”关键字的c ++仿真
【发布时间】:2019-10-17 12:28:19
【问题描述】:

直到 'super' 在 c++ 中实现,我一直在寻找一种方法来自己模拟它。 动机:这是一个典型的场景:

class A
{
    void SomeMethod();
}

class B : public A
{
    void SomeMethod() override;
}

void B::DoSomething()
{
    A::SomeMethod();
}

一切都很好,直到有人在两者之间插入一个类:

class C : public A
{
    void SomeMethod() override;
}

并更改继承:

class B : public C {...}

在大多数情况下,我希望直接调用基类,除非我明确地将所有 A:: 调用替换为 C:: 调用,否则不会发生这种情况。

“super”关键字在这里非常有用,它的意思是:“使用直接基数,但如果有歧义则发出编译器错误”。

阅读了一些建议,我试图定义如下:

class A
{
    void SomeMethod();

    protected:
        using super = A;
}

class C
{
    void SomeMethod();

    protected:
        using super = C;
}

void B::DoSomething()
{
    super::SomeMethod();
}

但是调用了 A::SomeMethod() 而不是 C::SomeMethod()...

编译器如何处理多个同名别名?

我该如何解决这个问题?

编辑:建议的其他问题是一个旧问题,可以通过使用现代 c++ 改进解决方案。

【问题讨论】:

  • 据我所知,super 由于多重继承,不会在 C++ 中实现。
  • 你的目标是什么编译器/平台?
  • Windows 和 Mac。
  • @gil_mo 真可惜 - 在 windows/msvc 上有一个编译器扩展 __super
  • Using "super" in C++的可能重复

标签: c++ inheritance keyword


【解决方案1】:

解决这个问题的一种方法,但它确实限制了你如何使用这个类,就是把它变成一个模板。在这样做时,您可以使基类成​​为模板类型,现在您有了可以引用它们的通用名称。看起来像

struct A
{
    void do_something() { std::cout << "A::do_something\n"; }
};

template <typename Super>
struct B : Super
{
    void do_something() 
    { 
        std::cout << "B::do_something\n"; 
        Super::do_something(); 
    }
};

template <typename Super>
struct C : Super
{
    void do_something() 
    { 
        std::cout << "C::do_something\n"; 
        Super::do_something(); 
    }
};

int main() 
{
    B<A> b;
    b.do_something();
    C<B<A>> c;
    c.do_something();
}

哪个输出

B::do_something
A::do_something
C::do_something
B::do_something
A::do_something

您甚至可以使用多重继承并单独访问每个基础

template <typename Super1, typename Super2>
struct B : Super1, Super2
{
    void do_something() 
    { 
        std::cout << "B::do_something\n"; 
        Super1::do_something(); 
        Super2::do_something(); 
    }
};

【讨论】:

  • 人们可能会将模板参数默认为继承应该是什么(所以我们可以写C&lt;&gt; c;,而不是让用户每次都背诵正确的继承层次结构)。每节课后那个或using C = CImpl&lt;B&gt;;
  • @MaxLanghof 我更喜欢这个使用理念。我不想以一种或另一种方式影响用户,所以我让他们决定他们实际想要如何使用它。
  • 我已将此回复标记为有帮助,但是 AFAIK 它不能作为最终答案,因为它需要对我的代码进行大规模重构...
【解决方案2】:

这个要求没有意义:哪个基类应该被认为是超类?

如果您的类具有单继承,那么您可以通过添加using 声明来减轻维护负担:

class B : public A
{
    using Base = A;
    //...
}

那么你只有一行需要更改。

【讨论】:

    猜你喜欢
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2018-09-18
    • 2018-05-30
    • 2013-03-19
    相关资源
    最近更新 更多