假设我的数据类型为enum TreeTypes { TallTree, ShortTree, MediumTree }
。
我必须根据一种特定的树类型初始化一些数据。
目前我已经写了这段代码:
int initialize(enum TreeTypes tree_type) {
if (tree_type == TallTree) {
init_tall_tree();
}
else if (tree_type == ShortTree) {
init_short_tree();
}
else if (tree_type == MediumTree) {
init_medium_tree();
}
return OK;
}
但这是一种愚蠢的代码重复。我没有使用任何强大的C ++功能,比如模板。
我怎样才能更好地编写此代码?
谢谢,Boda Cydo。
答案 0 :(得分:16)
您的代码适用于两个或三个值,但您是对的,当您拥有数百个时,您需要更具工业实力的东西。两种可能的解决方案:
使用类层次结构,而不是枚举 - 然后您可以使用虚函数并让编译器确定要调用的实际函数
创建枚举地图 - >函数,你在启动时初始化 - 你的函数调用变成类似map[enum]->func()
模板在这里工作得不好,因为你试图在运行时做出决定,而模板在编译时就做了。
答案 1 :(得分:7)
总之一句话:继承
class Tree { public: virtual void initialize() = 0; }
class ShortTree : public Tree {
public:
virtual void initialize(){
/* Short Tree specific code here */
}
}
class MediumTree : public Tree {
public:
virtual void initialize(){
/* Medium Tree specific code here */
}
}
class TallTree : public Tree {
public:
virtual void initialize(){
/* Tall Tree specific code here */
}
}
然后,只要你想调用initialize,就确保有一个指针或多态的引用才能正常工作:
Vector<Tree*> trees;
trees.push_back(new SmallTree());
trees.push_back(new MediumTree();
trees.push_back(new TallTree();
// This will call the tree specific code for each tree in the vector
for(vector<Tree*>::iterator tree = trees.begin(); tree!=trees.end(); ++tree)
tree->initialize();
答案 2 :(得分:1)
使用由枚举值索引的查找表(假设所有函数具有相同的签名),即:
enum TreeTypes { TallTree, ShortTree, MediumTree, MaxTreeTypes }
typedef void (*p_init_func)(void);
p_init_func initialize_funcs[MaxTreeTypes] =
{
&init_tall_tree,
&init_short_tree,
&init_medium_tree
};
int initialize(enum TreeTypes tree_type)
{
initialize_funcs[tree_type]();
return OK;
}
答案 3 :(得分:0)
尝试使用switch语句:
int initialize(enum TreeTypes tree_type) {
switch (tree_type) {
case TallTree:
init_tall_tree();
break;
case ShortTree:
init_short_tree();
break;
case MediumTree:
init_medium_tree();
break;
}
return OK;
}
答案 4 :(得分:0)
如果这种初始化确实是唯一的区别,那么我不确定任何其他成语会改善这种情况。
你可以从Tree继承并创建正确类型的树对象......但是你仍然需要区分哪一个实例化,所以你仍然会在某个地方找到类似的if / else块。< / p>
也就是说,如果不仅仅是初始化不同,你应该子类化并使用虚函数来实现它们之间的差异。
答案 5 :(得分:0)
以及您在标记中指出的模板方式:
enum TreeTypes { Tall, Short, Medium };
struct TreeBase {
// (...)
};
struct TallTree : public TreeBase {
// (...)
};
struct ShortTree : public TreeBase {
// (...)
};
struct MediumTree : public TreeBase {
// (...)
};
template<TreeTypes N_type = Tall>
struct Tree : public TallTree {
// (...)
};
template<>
struct Tree<Short> : public ShortTree {
// (...)
};
template<>
struct Tree<Medium> : public MediumTree {
// (...)
};
这样你就可以通过基指针访问每种树类型的单独类。将它们包装到Tree类中可以实现:
Tree<Tall> tall_tree;
Tree<Short> short_tree;
Tree<Medium> medium_tree;