我的编码风格包括以下习语:

class Derived : public Base
{
   public :
      typedef Base super; // note that it could be hidden in
                          // protected/private section, instead
      
      // Etc.
} ;

这使得我可以使用“super”作为Base的别名,例如,在构造函数中:

Derived(int i, int j)
   : super(i), J(j)
{
}

甚至当从被重写版本的基类中调用该方法时:

void Derived::foo()
{
   super::foo() ;

   // ... And then, do something else
}

它甚至可以被链接(尽管我仍然需要找到它的用途):

class DerivedDerived : public Derived
{
   public :
      typedef Derived super; // note that it could be hidden in
                             // protected/private section, instead
      
      // Etc.
} ;

void DerivedDerived::bar()
{
   super::bar() ; // will call Derived::bar
   super::super::bar ; // will call Base::bar

   // ... And then, do something else
}

无论如何,我发现“typedef super”的使用非常有用,例如,当Base是verbose和/或模板化的时候。

事实上,super是在Java和c#中实现的(在c#中,它被称为“base”,除非我错了)。但是c++缺少这个关键字。

我的问题是:

这种typedef的使用在你工作的代码中是超级常见/罕见/从未见过吗? 这种typedef的使用是超级Ok(也就是说,你看到强烈或不那么强烈的理由不使用它)? “super”应该是一个好东西吗?它应该在c++中标准化吗?或者通过类型定义来使用已经足够了吗?

编辑:Roddy提到的事实类型定义应该是私有的。这意味着任何派生类在不重新声明它的情况下都不能使用它。但我猜它也会阻止super::super链接(但谁会为它哭泣呢?)

编辑2:现在,在大量使用“super”几个月后,我完全同意罗迪的观点:“super”应该是私人的。


当前回答

Super(或inherited)是非常好的东西,因为如果你需要在Base和Derived之间插入另一个继承层,你只需要改变两件事:“class Base: foo”和2。的类型定义

如果我没记错的话,c++标准委员会正在考虑为这个添加一个关键字…直到迈克尔·蒂曼(Michael Tiemann)指出这种类型的技巧是有效的。

至于多重继承,因为它在程序员的控制下,你可以做任何你想做的:也许是super1和super2,或者其他什么。

其他回答

Bjarne Stroustrup在《c++的设计与发展》一书中提到,在c++第一次标准化时,ISO c++标准委员会就考虑将super作为关键字。

Dag Bruck提出了这个扩展,称基类为“继承的”。该提案提到了多重继承问题,并标记了不明确的用途。甚至斯特劳斯特鲁普也被说服了。

经过讨论,Dag Bruck(是的,就是提出该提案的同一个人)写道,该提案是可实现的,技术上是合理的,并且没有重大缺陷,并且处理了多重继承。另一方面,这并没有带来足够的回报,委员会应该处理一个更棘手的问题。

Michael Tiemann来晚了,然后用这篇文章中提到的同样的技巧展示了一个typedef'ed super可以很好地工作。

所以,不,这可能永远不会标准化。

如果你没有副本,《Design and Evolution》的封面价格也物有所值。用过的拷贝花10美元就能买到。

我不知道这种情况是否罕见,但我肯定也做过同样的事情。

正如前面所指出的,当一个类使用多重继承时,这部分语言本身的困难就出现了。

我经常用这个。就在我发现自己输入了几次基类类型时,我将用一个类似于您的类型定义替换它。

我认为这是一个很好的用途。如前所述,如果基类是模板,则可以节省输入。此外,模板类可以接受参数,作为模板应该如何工作的策略。只要基类的接口保持兼容,您就可以自由地更改基类类型,而不必修复对它的所有引用。

我认为通过typedef的使用已经足够了。无论如何,我不知道它将如何构建到语言中,因为多重继承意味着可以有许多基类,因此您可以根据逻辑上认为最重要的基类的类型定义它。

我不会说太多,除了目前的代码注释,说明super并不意味着调用base!

超级!=基本。

简而言之,“超级”到底是什么意思?那么"base"是什么意思呢?

Super表示调用方法的最后一个实现者(不是基方法) 基是指在多重继承中选择哪个类是默认基。

这两条规则适用于类的typedefs。

考虑库的实现者和库的用户,谁是超级谁是基础?

更多信息,这里是工作代码复制粘贴到您的IDE:

#include <iostream>

// Library defiens 4 classes in typical library class hierarchy
class Abstract
{
public:
    virtual void f() = 0;
};

class LibraryBase1 :
    virtual public Abstract
{
public:
    void f() override
    {
        std::cout << "Base1" << std::endl;
    }
};

class LibraryBase2 :
    virtual public Abstract
{
public:
    void f() override
    {
        std::cout << "Base2" << std::endl;
    }
};

class LibraryDerivate :
    public LibraryBase1,
    public LibraryBase2
{
    // base is meaningfull only for this class,
    // this class decides who is my base in multiple inheritance
private:
    using base = LibraryBase1;

protected:
    // this is super! base is not super but base!
    using super = LibraryDerivate;

public:
    void f() override
    {
        std::cout << "I'm super not my Base" << std::endl;
        std::cout << "Calling my *default* base: " << std::endl;
        base::f();
    }
};

// Library user
struct UserBase :
    public LibraryDerivate
{
protected:
    // NOTE: If user overrides f() he must update who is super, in one class before base!
    using super = UserBase; // this typedef is needed only so that most derived version
    // is called, which calls next super in hierarchy.
    // it's not needed here, just saying how to chain "super" calls if needed

    // NOTE: User can't call base, base is a concept private to each class, super is not.
private:
    using base = LibraryDerivate; // example of typedefing base.

};

struct UserDerived :
    public UserBase
{
    // NOTE: to typedef who is super here we would need to specify full name
    // when calling super method, but in this sample is it's not needed.

    // Good super is called, example of good super is last implementor of f()
    // example of bad super is calling base (but which base??)
    void f() override
    {
        super::f();
    }
};

int main()
{
    UserDerived derived;
    // derived calls super implementation because that's what
    // "super" is supposed to mean! super != base
    derived.f();

    // Yes it work with polymorphism!
    Abstract* pUser = new LibraryDerivate;
    pUser->f();

    Abstract* pUserBase = new UserBase;
    pUserBase->f();
}

这里还有一点很重要:

多态呼叫:向下呼叫 超级呼叫:向上呼叫

在main()内部,我们向下使用多态调用,而super向上调用,这在实际生活中并不是很有用,但它说明了两者的区别。

这种typedef的使用在你工作的代码中是超级常见/罕见/从未见过吗?

我从未在我使用的c++代码中见过这种特殊的模式,但这并不意味着它不在那里。

这种typedef的使用是超级Ok(也就是说,你看到强烈或不那么强烈的理由不使用它)?

它不允许多重继承(至少很干净)。

“super”应该是一个好东西吗?它应该在c++中标准化吗?或者通过类型定义来使用已经足够了吗?

由于上述引用的原因(多重继承),没有。你在你列出的其他语言中看到“super”的原因是它们只支持单继承,所以“super”指的是什么是没有混淆的。诚然,在这些语言中它是有用的,但在c++数据模型中却没有一席之地。

哦,顺便说一句:c++ /CLI以“__super”关键字的形式支持这个概念。但是请注意,c++ /CLI也不支持多重继承。