dynamic_cast来解决实现难题

dynamic_cast to solve an implementation dilemma

本文关键字:实现 难题 解决 cast dynamic      更新时间:2023-10-16

这件事让我沮丧了一个多星期。我已经在这个网站上浏览了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函数的实现。

现在,我终于有了一个使用上述基类的类C。

class C
{
    public:
    baseClass *allocator ; 
    Allocate(int size) ; 
    Free(void) ; 
}

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

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。这个问题有更清洁的解决方案吗?

基类设计存在问题,这就是为什么在派生级别存在实现问题。

如果我有一个指向baseClass实例的指针(无论它必须是什么实际类型),那么Allocate方法的隐含约定是,我可以传递一个指向任何类型的baseClass::recordBase的指针,一切都应该正常。

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

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

virtual recordBase* Allocate(int size) = 0;

带有

virtual derivedRecordA* Allocate(int size);

提供size不应该是数组大小,并且您没有试图返回指向派生对象数组的指针,这对基类接口的用户来说也是有问题的。

你真的需要用基类函数的契约和预期行为来扩展你的问题,这些重写应该是为了得到更好的答案。

有一个更干净的解决方案,它在baseRecord上使用一个虚拟函数,该函数被适当地重写。

如果这不令人满意,则检查typeid并在成功时使用static_cast可能比dynamic_cast更快,即使它是糟糕的耦合。