给出这个例子:
struct Base {
void func() { }
};
struct NoOtherBase : public Base {
};
struct OtherBase : public Base {
};
struct HasOtherBase : public OtherBase,
public Base {
};
struct RandomBase : public Base {
};
struct RandomOtherBase : public RandomBase {
};
struct MultipleOtherBases : public RandomOtherBase,
public Base {
};
template <class T>
void randomFunc(T* val) {
/* Find out if T derives from any other class
* based on Base at compile time.
*
* T = NoOtherBase -> false
* T = HasOtherBase -> true
* T = MultipleOtherBases -> true
*/
constexpr bool hasAnotherBase = /* ... */;
// Cast val to the found Base without runtime costs
// and call the func() method.
base->func();
}
真正的问题是val
已经从Base派生。挑战在于寻找其他基地。如果T为HasOtherBase
,则应调用func
的{{1}}。如果T不符合规范,编译器可能会抛出随机错误。
可以使用C ++ 11的所有功能。
答案 0 :(得分:1)
您可以在Base *上使用dynamic_cast来查询任何派生类:
void randomFunc(Base* b)
{
OtherBase* hob = dynamic_cast<OtherBase*>(b);
if (hob != nullptr)
hob->func();
NoOtherBase* nob = dynamic_cast<NoOtherBase*(b);
if (nob != nullptr)
nob->func();
// ...
}
当然,在这种情况下,这是毫无意义的,因为只有一种“func”方法。只有某些派生类提供了自己的非覆盖版本的“func”才有意义。
另一件需要考虑的事情是,如果您只想在HasOtherBases或MultipleOtherBases对象中使用Base的实例数据的一个版本,您应该虚拟地从Base派生,否则您将遇到“钻石”问题。如果没有虚拟继承,MultipleOtherBases对象将在运行时具有以下结构:
如果您将代码更改为:
struct Base {
void func() { }
};
struct RandomBase : public virtual Base {
};
struct RandomOtherBase : public RandomBase {
};
struct MultipleOtherBases : public RandomOtherBase,
public virtual Base {
};
然后它将在运行时具有以下结构:
答案 1 :(得分:1)
由于示例中的所有类都继承了Base
,为什么不将func
声明为virtual
?
struct Base {
virtual void func() { }
};
struct OtherBase : public Base {
void func() { //other stuff than in Base implementation }
};
然后直接在您的实例上调用func
- val->func()
- 并且func
的虚拟属性将负责调用func
的派生程度最高的实例。