如何基于变量值习惯性地调用C ++函数?

时间:2010-08-05 20:01:47

标签: c++ templates repeat

假设我的数据类型为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。

6 个答案:

答案 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;