假设有一个模板类,它是一个抽象接口,可以跟踪一系列数据。
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;}
};
有两个类,每个类都从IT
和ST
继承,并且两个都需要从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...else
或switch...case
时,这很烦人,尤其是当类型越来越多时。
是否可以更巧妙地转换类型?如果我可以始终(或在大多数情况下)使用A的指针来完成所有工作,那将是很好的。
答案 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);