我的编码风格包括以下习语:
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并不意味着调用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向上调用,这在实际生活中并不是很有用,但它说明了两者的区别。