我的编码风格包括以下习语:
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是详细和/或模板时.
事实上,super是用Java实现的,也是用C#实现的(除非我错了,否则称为"base").但是C++缺少这个关键字.
所以,我的问题:
这是使用typedef超常见/稀有/从未在您使用的代码中看到过吗?
这是使用typedef super Ok(即你是否看到强大或不那么强烈的理由不使用它)?
应该"超级"是一件好事,它应该在C++中有些标准化,还是已经足够使用typedef?
编辑:罗迪提到了typedef应该是私有的事实.这意味着任何派生类都无法在不重新声明的情况下使用它.但我想这也会阻止super :: super chaining(但是谁会为此而哭?).
编辑2:现在,在大量使用"超级"之后的几个月,我全心全意地赞同罗迪的观点:"超级"应该是私人的.我会两次回答他的答案,但我想我不能.
Bjarne Stroustrup在C++的设计和演变中提到,super
作为关键词,ISO C++标准委员会首次考虑C++是标准化的.
Dag Bruck提出了这个扩展,称基类为"继承".该提案提到了多重继承问题,并且会标记含糊不清的用法.甚至Stroustrup也深信不疑.
经过讨论,Dag Bruck(是的,提出提案的人)写道,该提案是可实现的,技术上合理,没有重大缺陷,并处理多重继承.另一方面,没有足够的收益,委员会应该处理棘手的问题.
Michael Tiemann迟到了,然后表明一个typedef'ed super会工作得很好,使用的技术与本文中提到的相同.
所以,不,这可能永远不会标准化.
如果您没有副本,Design and Evolution非常值得支付.使用过的副本大约需要10美元.
我总是使用"继承"而不是超级.(可能是由于Delphi背景),并且我总是把它设为私有,以避免在类中错误地省略'inherited'但子类试图使用它时的问题.
class MyClass : public MyBase { private: // Prevents erroneous use by other classes. typedef MyBase inherited; ...
我用于创建新类的标准"代码模板"包括typedef,因此我几乎没有机会忽略它.
我不认为链接的"超级超级"建议是个好主意 - 如果你这样做,你可能很难与特定的层次结构联系起来,而改变它可能会严重破坏它.
这样做的一个问题是,如果你忘记(重新)为派生类定义super,那么对super :: something的任何调用都可以正常编译,但可能不会调用所需的函数.
例如:
class Base { public: virtual void foo() { ... } }; class Derived: public Base { public: typedef Base super; virtual void foo() { super::foo(); // call superclass implementation // do other stuff ... } }; class DerivedAgain: public Derived { public: virtual void foo() { // Call superclass function super::foo(); // oops, calls Base::foo() rather than Derived::foo() ... } };
(正如Martin York在对这个答案的评论中指出的那样,可以通过使typedef为私有而不是公共或受保护来消除这个问题.)
FWIW Microsoft已在其编译器中添加了__super的扩展名.
超级(或继承)是非常好的事情,因为如果你需要在Base和Derived之间粘贴另一个继承层,你只需要改变两件事:1."class Base:foo"和2. typedef
如果我没记错的话,C++标准委员会正在考虑为此添加一个关键字......直到Michael Tiemann指出这种类型的def技巧有效.
至于多重继承,因为它在程序员控制下你可以做任何你想做的事:也许是super1和super2,或者其他什么.
我刚刚找到了另一种解决方法.我有一个关于typedef方法的一个大问题,今天让我感到困惑:
typedef需要类名的精确副本.如果有人更改了类名但没有更改typedef,那么您将遇到问题.
所以我想出了一个使用非常简单的模板的更好的解决方案.
templatestruct MakeAlias : C { typedef C BaseAlias; };
所以现在,而不是
class Derived : public Base { private: typedef Base Super; };
你有
class Derived : public MakeAlias{ // Can refer to Base as BaseAlias here };
在这种情况下,BaseAlias
不是私密的,我试图通过选择应提醒其他开发人员的类型名称来防止粗心使用.
我不记得以前见过这个,但乍一看我喜欢它.正如Ferruccio指出的那样,面对MI,它并不能很好地发挥作用,但是MI更像是一个例外而不是规则,并且没有任何东西可以说任何东西都需要在任何地方都可以使用.
我已经在许多代码中看到了这个习惯用法,我很确定我甚至在Boost的库中看到过它.但是,据我记得,最常见的名字是base
(或Base
)而不是super
.
如果使用模板类,这个习惯用法特别有用.作为示例,请考虑以下类(来自实际项目):
templateclass Finder >, PizzaChiliFinder> : public Finder >, Default> { typedef Finder >, Default> TBase; // … }
不要介意有趣的名字.这里重要的一点是继承链使用类型参数来实现编译时多态.不幸的是,这些模板的嵌套级别非常高.因此,缩写对于可读性和可维护性至关重要.