dynamic_cast解决了实施困境

时间:2014-04-21 20:27:37

标签: c++ dynamic-cast

这让我感到沮丧一个多星期。我在这个网站上经历了关于dynamic_casting的各种线程,但我仍然不确定实现它的最佳方法是什么。

所以我有一个像这样的基类:

class baseClass
{
    public:

        class recordBase
        {
            public:
                virtual ~recordBase(){}
        };

        virtual ~baseClass() {};
        virtual bool Allocate( int size, 
                   recordBase *outRecord) = 0 ;
        virtual bool Free(recordBase *allocRecord) = 0;
} ;

这有两个派生类。 派生类A如此......

class DerivedA  : public baseClass
{
    public:

        class derivedRecordA : public baseClass::recordBase
        {
            public:
                inline ~derivedRecordA(){} ; 
                someClass *obj1 ;
         }
         bool Allocate(int size, 
                 baseClass::recordBase *outRecord);
         bool Free(baseClass::recordBase *allocRecord) ;
}

我有一个类似的派生类' DerivedB'它有自己的dervied recordBase和Allocate和Free函数的实现。

现在最后我有一个使用上面的baseClass的C类。

class C
{
    public:
    baseClass *allocator ; 

    Allocate(int size) ; 
    Free(void) ; 
}

现在这是我的问题,基于某些条件,C类要么存储一个分配器,它是derivedA,要么存储一个是derivedB。

C类的分配函数如下所示

C::Allocate(int size)
{
    //condition where DerivedA is needed       
    DerivedA::derivedRecordA recObj ;

    if(allocator->Allocate(size, &recObj)) 
    {
        return true;
    }
    else return false ; 
}

现在问题是我被迫在DerivedA :: Allocate实现中使用动态转换,如下所示:

DerivedA::Allocate(int size, baseClass:recordBase *outRecord)
{
    DerivedA::derivedRecordA *rec = dynamic_cast<  DerivedA::derivedRecordA *>(outRecord) ;

     //allocate mem and store info in 'rec'
     return true ;
}

如何避免在此处使用dynamic_casting。这个问题有更清洁的解决方案吗?

2 个答案:

答案 0 :(得分:1)

您的基类设计存在问题,这就是您在派生级别遇到实施问题的原因。

如果我有一个指向baseClass实例的指针(无论它必须是什么类型),那么Allocate方法的隐含契约就是我可以传入一个指向 any的指针 baseClass::recordBase,事情应该有效。

如果派生类覆盖了函数,那么它们不应该缩小函数用户的函数要求。这实际上意味着它们提供的覆盖不满足基类功能的接口。如果他们需要这个,那么他们应该提供一个具有合适界面的不同功能。

话虽如此,我本来期望Allocate函数分配一个新对象。在这种情况下,您可以覆盖并返回指向特化的指针(这称为协变返回类型)。例如,您可以覆盖:

virtual recordBase* Allocate(int size) = 0;

virtual derivedRecordA* Allocate(int size);

提供 size不应该是一个数组大小而你不是要尝试返回一个指向派生对象数组的指针,这也会产生问题对于基类接口的用户。

你真的需要扩展你的问题,你的基类功能的合同和预期行为以及那些覆盖应该是为了得到更好的答案。

答案 1 :(得分:0)

有一个更清洁的解决方案,它使用baseRecord上的虚拟函数,该函数被适当地覆盖。

如果不满意,检查typeid并在成功时使用static_cast可能会比dynamic_cast更快,即使它是错误的耦合。