搜索也从某个类继承并强制转换为它的基类

时间:2012-12-29 18:29:01

标签: c++ c++11

给出这个例子:

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的所有功能。

2 个答案:

答案 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对象将在运行时具有以下结构:

enter image description here

如果您将代码更改为:

struct Base {
    void func() { }
};

struct RandomBase : public virtual Base {
};

struct RandomOtherBase : public RandomBase {
};

struct MultipleOtherBases : public RandomOtherBase,
    public virtual Base {
};

然后它将在运行时具有以下结构:

enter image description here

答案 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的派生程度最高的实例。