将继承的对象强制转换为正确的子类的最佳实践

时间:2018-11-19 10:03:29

标签: c++ inheritance

我有两个班,每个班都有几个孩子:

class ContainerGeneral {...};
class ContainerTypeA : ContainerGeneral {
public:
    void doSomethingA();
};
class ContainerTypeB : ContainerGeneral {
    void doSomethingB();
};

class InterpreterGeneral {
protected:
    ContainerGeneral* container;
};

class InterpreterTypeA : InterpreterGeneral {
public:
    void saveContainer(ContainerTypeA* cont) {
        container = cont;
    }
};

class InterpreterTypeB : InterpreterGeneral {
public:
    void saveContainer(ContainerTypeB* cont) {
        container = cont;
    }
};

Interpreter类用于相应类型的容器(AABBGeneral至{ {1}})。为此,我向General对象添加了一个指向InterpreterGeneral对象的成员指针。我希望ContainerGeneral将此对象作为InterpreterGeneral来寻址,但我希望继承的类将能够寻址与适当类型的容器相同的容器。我可以通过在寻址时继承继承类的指针来做到这一点(仅示例ContainerGeneral以节省空间)

A

或者通过添加一个继承类型的新成员指针来指向与容器相同的位置:

(ContainerTypeA*)container->doSomethingA();

在这种情况下,最佳实践是什么?有没有一种方法可以做到尽可能干净,而不必每次都进行转换,并且不添加不包含任何“新”信息的新成员?

2 个答案:

答案 0 :(得分:0)

如果您需要有关InterpreterTypeAInterpreterTypeB中的容器实例的具体类型信息,请通过不在代码GeneralContainer*中存储GeneralInterpreter数据成员来在代码中表达这一点({ {1}}数据成员在任何情况下都是值得商bat的),而是子类protectedContainerTypeA*中具体的ContainerTypeB*InterpreterTypeA数据成员。存储基类指针,然后通过强制转换来规避其限制,这掩盖了需要具体类型信息的事实。

此外,在容器基类中提供InterpreterTypeBdoSomethingA()的空默认实现,或者将它们转换为doSomethingB()纯成员函数并将空移实现到virtualContainerTypeA中。然后,只需调用它们就很安全-当它是不需要的具体类型时,它们将不会做任何事情。

最后一个学究的侧面说明:我看不出有任何理由在层次结构中将派生类称为“ son”类。常用术语是“孩子”类。

答案 1 :(得分:0)

您要处理的问题具有virtual functions形式的解决方案。试试这个:

class ContainerGeneral {
public:
    virtual void doSomething() = 0;
};

class ContainerTypeA : public ContainerGeneral {
public:
    void doSomething() {
        std::cout << "Hello A!" << std::endl;
    };
};

class ContainerTypeB : public ContainerGeneral {
public:
    void doSomething() {
        std::cout << "Hello B!" << std::endl;
    };
};

因此,您完全不必担心从InterpreterGeneral继承:

class InterpreterGeneral {
public:
    void doSomething()
    {
        container->doSomething();
    }
private:
    ContainerGeneral* container;
};

旁注:当然,这会产生一些运行时开销。如果您在运行时不需要多态,则可以避免这种情况。看看the static polymorphism。仅当您是忍者。