使用虚函数vs dynamic_cast

时间:2013-12-30 16:53:41

标签: c++ function virtual dynamic-cast

不使用虚拟功能,可以使用以下内容:

void BaseClass::functionName () {  // BaseClass already has virtual functions
    // some LONG code true for all derived classes of BaseClass
    // ...
    if (typeid (*this) == typeid (DerivedClass1))
        // use functions of DerivedClass1 on dynamic_cast<DerivedClass1*>(this)
    else if (typeid (*this) == typeid (DerivedClass2))
        // use functions of DerivedClass2 on dynamic_cast<DerivedClass2*>(this)

    // some LONG code true for all derived classes of BaseClass
    // ...
 }

只是我觉得将虚函数用于上述类似的东西并不是一个好主意,因为它只是一个专门用于派生类的小部分。然后,需要对所有派生类反复使用用于所有派生类的长代码(仅为此建议一个辅助函数)。当然,我已经测试了我的方法并且它有效(并且我认为没有性能损失),但我想知道这是否是可疑的做法。 如果if-else-if部分在函数中被多次使用怎么办?

如果所有派生类的公共代码是相对短的,那么最好使用虚函数,对吗?

4 个答案:

答案 0 :(得分:2)

为什么不这样做:

void BaseClass::functionName () {
    // some LONG code true for all derived classes of BaseClass
    // ...

    this->some_protected_virtual_member_function();

    // some LONG code true for all derived classes of BaseClass
    // ...
 }

因此,公共部分不会重复,并且行为仍然可以轻松地在子类中具有扩展,而无需向父类添加另一个if

答案 1 :(得分:0)

除非类具有虚函数,否则您的代码将无法运行。 C ++只提供有限的反射:如果没有虚函数,则typeid(DerivedClass1)== typeid(DerivedClass2)。上面的代码也可能比简单地访问虚函数慢:你将为每种类型获得一个新的分支,而不是一个恒定的时间指针查找。

然而,上述代码的最大问题是它失去了多态性和封装。必须知道使用代码或DerivedClass1和DerivedClass2需要做什么。它需要知道DerivedClass1和DerivedClass2中的结构。此外,所有代码都堆积在一个地方,使这个功能可能有数百行。

答案 2 :(得分:0)

我认为你在这里寻找模板方法模式:只需使用你现有的非虚函数,并让它只调用具体类之间差异的一小部分代码。它的优点是看起来更漂亮。

void BaseClass::functionName () {
    // some LONG code true for all derived classes of BaseClass
    // ...

    functionName_impl();  // Will be virtual (private or protected) and overriden in each child class to do the right work.

    // some LONG code true for all derived classes of BaseClass
    // ...
 }

答案 3 :(得分:0)

这是Template Method Pattern

的退化案例
class Base {
public:
    void templated() {
        // do some stuff

        this->hook1();

        // other stuff

        if (/*cond*/) { this->hook2(); }

        size_t acc = 0;
        for (Stuff const& s: /*...*/) { acc += this->hook3(s); }

        // other stuff
    }

private:
    virtual void hook1() {}
    virtual void hook2() {}
    virtual size_t hook3(Stuff const&) { return 0; }
}; // class Base

然后Derived类可以自定义挂钩的行为。

警告:由于templated方法不是virtual,因此本质上非常严格。这既是一种美德又是这种模式的问题,这很好,因为如果你需要改变templated方法,那么它就是在一个地方定义的,如果提供的钩子不足以定制它就很烦人行为。