无需动态转换即可复制派生类属性的方法

时间:2014-05-03 00:33:15

标签: c++ polymorphism dynamic-cast double-dispatch

我试图找到一种有效的方法(使用多态)在外部复制两个派生类之间的特定属性。我有一组派生自基类DataClassA的数据类。我想在一个单独的过滤器类中对这些数据类进行操作,该过滤器类将DataClassA引用作为输入和输出参数。过滤器将执行DataClassA共同的必要操作,但我还想将特定于类的属性从输入传播到输出类。考虑:

class DataClassA
{
public:
    virtual void copyAttributes( DataClassA& copyFrom );
}

class DataClassB : public DataClassA
{
public:
    virtual void copyAttributes( DataClassA& copyFrom );
};

class DataFilter
{
    void run( DataClassA& input, DataClassB& output )
    {
        //do some calculations here
           ...
        //then copy over attributes
        output.copyAttributes( input );
    }
};

我的问题显然是copyAttributes()依赖于需要知道输入和输出派生类的类型(它们不一定必须相同)。但是,过滤器只处理对基类DataClassA的引用。我的反应是简单地建立一个dynamic_cast,虽然我冒着被打的手(以及其他可能的负面后果)。如果我这样做,我只需为每个派生类创建一个copyAttributes方法,该类调用父类的copyAttributes,然后使用dynamic_cast查看copyFrom对象属于同一类型:

void DataClassB::copyAttributes( DataClassA& copyFrom )
{
    //copy attributes from parent class  
    DataClassA::copyAttributes( copyFrom );

    //test if the class being copied from is of type DataClassB
    DataClassB* copyPtr = dynamic_cast<DataClassB*>&copyFrom;
    if( copyPtr != NULL )
    {
        //copy DataClassB-specific attributes from copyFrom to this
        ...
    }
}

我在这个问题上找到的最相似的帖子是Virtual functions and polymorphism。我的主要问题是:1)我建议使用dynamic_cast不合适吗? 2)如果是这样,我怎么能以另一种方式实现这个copyAttributes?有人提到使用访客设计模式虽然我不确定它会是什么样子。

这是Visualization Toolkit(VTK)所做的更简单的版本,因为我使用了对许多不同数据类进行操作的过滤器类。有趣的是,他们通过包含宏的方式处理RTTI,这些宏包括类和父类的字符串名称,可以直接比较它们以正确地向下转换数据类型。

1 个答案:

答案 0 :(得分:0)

您似乎想要多次发送(就像我在这里所做的那样:https://ideone.com/8VxALs
这要求访问者知道每个派生类型。

另一种方法是每次使用dynamic_cast

可以按照以下方式进行简单的双重调度:

class DataClassA
{
public:
    virtual ~A() {}
    virtual void copyAttributes(DataClassA& copyFrom) { copyFrom.copyAttributesToA(*this); }
    virtual void copyAttributesToA(DataClassA& copyTo) { /* Implementation to copy A -> A */ }
    virtual void copyAttributesToB(DataClassB& copyTo) { /* Implementation to copy A -> B */ }  
};

class DataClassB : public DataClassA
{
public:
    void copyAttributes(DataClassA& copyFrom) override { copyFrom.copyAttributesToB(*this); }
    void copyAttributesToA(DataClassA& copyTo) override { /* Implementation to copy B -> A */ }
    void copyAttributesToB(DataClassB& copyTo) override { /* Implementation to copy B -> B */ }
};