当它被称为shared_ptr <basic> </basic>时调用Derived类方法

时间:2013-05-27 13:08:21

标签: c++ oop templates casting

我坚信这是一个非常常见的面向对象的问题,但谷歌的搜索并没有给我一个答案。我希望,有人可以指出我正确的方式如何摆脱我的僵局。我尝试了解并使用标准技术并避免重新发明轮子。

简而言之:

class A {
protected:
    int _A;
public:
    virtual void commonMethod() = 0;
    void methodForMember_A();
}

class B : public A {
protected:
    int _B;
public:
    virtual void commonMethod()
    void methodForMember_B();
}

class C : public B {
protected:
    int _C;
public:
    virtual void commonMethod()
    void methodForMember_C();
}

class Basic {
protected:
    // B or C instance
    shared_ptr<A> _smth;
public:
    Basic(shared_ptr<A> a_ptr) : _smth(a_ptr);
    // calls A/B/C->commonMethod();
    void commonMethod();
}

// Which works with B
class MoreSpecific : public Basic {
public:
    MoreSpecific(shared_ptr<B> b_ptr) : Basic(b_ptr);
    // calls b->methodForMemberB();
    void specificMethod();
}

问题出在specificMethod(),我希望致电_smth->methodForMemberB()

我可以看到以下方式:

  1. 投放所有specificMethods()? (在我看来,铸件是一种救生艇,必须在非常复杂的情况下使用)

  2. 模板的时间? (不确定模板是否合适)

  3. 设计绝对错误?

  4. 提前谢谢。

2 个答案:

答案 0 :(得分:2)

如果MoreSpecific接口仅对B个实例有效,则必须确保不将A个对象设置为Basic::_smth。您可以使用基类模板

来完成此操作
template<typename T>
class BasicBase {
protected:
    shared_ptr<T> _smth;
public:
    BasicBase (shared_ptr<T> a_ptr) : _smth(a_ptr);

    void commonMethod();
}

typedef BasicBase <A> Basic;


// Which works with B only
class MoreSpecific : public Basic<B> {
public:
    MoreSpecific(shared_ptr<B> b_ptr) : Basic(b_ptr);
    // calls b->methodForMemberB();
    void specificMethod();
}

答案 1 :(得分:2)

问题在于,当您使用/依赖Basic来存储B指针时,您将丢失不仅仅是A实例的信息。在这种情况下,您没有遵循(Liskov)继承原则!

有几种方法可以解决这个问题。模板是一种方式,但它取决于具体情况,在这种情况下,更“面向接口”的解决方案可能是合适的。在这种情况下的问题是您将B存储在基类中,这就是我们在此避免的。相反,使用抽象接口:

class Basic {
protected:
    virtual shared_ptr<A> getPtr () = 0; 
public:
    // calls A/B/C->commonMethod();, uses getPtr ()
    void commonMethod();
};

// Which works with B
class MoreSpecific : public Basic {
protected:
    // Store and implement interface for base classes
    shared_ptr<B> b_ptr;
    shared_ptr<A> getPtr () {return b_ptr;}
public:
    MoreSpecific(shared_ptr<B> b_ptr) : b_ptr(b_ptr);
    // calls b->methodForMemberB();
    void specificMethod();
};

如果你真的需要一个存储裸A ptr的类,你可以让该类实现Basic接口。要学习的一般教训是:没有数据成员的抽象接口是个好主意!