在多继承方案中动态转换类型

时间:2019-01-16 20:10:54

标签: c++

假设有一个模板类,它是一个抽象接口,可以跟踪一系列数据。

template<typename T>
class SeriesData
{
    virtual T valueAt(int i) const = 0;
};

我决定使用向量来存储数据,以便从中继承数据,我还添加了一个向序列添加值的函数。

template<typename T> class MySeriesData : public SeriesData<T>
{
    T valueAt(int i) const {return values_[i];}
    void add(const T& value) {values_.push_back(value);}
private:
    std::vector<T> values_;
};  

将要使用一系列数据的类。

template<typename T>
class AT
{
public:
    T data() const {return data_;}
    void setData(SeriesData<T>* data) {delete data_; data_ = data;}

private:
    SeriesData<T> *data_;
};

class IT : public AT<int>
{
};

class ST : public AT<string>
{
};

还有一个实现一些常见逻辑的类:

class A
{
public:
    A(){}
    virtual ~A() {}
protected:
    void common() {cout << "A common" << endl;}
};

有两个类,每个类都从ITST继承,并且两个都需要从A继承。我想让它们从A继承,因为有很多共同的逻辑。

class Numbers : public A , public IT
{
};

class Strings : public A , public ST
{
};

在主要逻辑中,我将使用A类型的指针根据客户端所需的类型动态创建Numbers或Strings的实例。

A* item;
if(type == NUMBER)
    item = new Numbers();
else if(type == STRING)
    item = new Strings();

我可以用item做那些普通的事情,这很好。

item->common();

但是,对于那些与AT相关的逻辑。我需要检查实型然后进行强制转换。

item->common();    
if(type == NUMBER)
{
    IT* itemNumber = static_cast<Numbers*>(item);
    itemNumber->setData(new MySeries<int>());  
}
else if(type == STRING)
{
    ST* itemString = static_cast<Strings*>(item);
    itemString->setData(new MySeries<string>());  
}

.....
if(type == NUMBER)
{
    //Have to cast from A to the a type of AT first
    Numbers* itemNumber = static_cast<Numbers*>(item);
    //Another conversion
    MySeries<int>* numberValues = (MySeries<int>*)itemNumber->data();
    numberValues->add(1); 
}
else if(type == STRING)
{
    Strings* itemString = static_cast<Strings*>(item);
    MySeries<string>* stringValues = (MySeries<string>*)itemString->data();
    stringValues->add("1");   
}

当代码中充满了这些if...elseswitch...case时,这很烦人,尤其是当类型越来越多时。

是否可以更巧妙地转换类型?如果我可以始终(或在大多数情况下)使用A的指针来完成所有工作,那将是很好的。

1 个答案:

答案 0 :(得分:1)

您可以将type依赖的操作包装在辅助功能中,该功能存储在以type为键的查找表中,例如:

std::map<int, A*(*)()> makeAMap;
makeAMap[NUMBER] = []() -> A* { return new B; };
makeAMap[STRING] = []() -> A* { return new C; };
...

std::map<int, void(*)(A*)> getFuncMap;
getFuncMap[NUMBER] = [](A *item){ static_cast<B*>(item)->get(); };
getFuncMap[STRING] = [](A *item){ static_cast<C*>(item)->get(); };
...

A* item = makeAMap[type]();
...
item->common();    
getFuncMap[type](item);

Live Demo