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