繁体   English   中英

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

[英]How to idiomatically call C++ functions based on variable value?

假设我有一个数据类型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。

您的代码对于两个或三个值是可以的,但是您是对的,当您拥有数百个时,您需要更具工业实力的东西。 两种可能的解决方

  • 使用类层次结构,而不是枚举 - 然后您可以使用虚函数并让编译器确定要调用的实际函数

  • 创建一个enum - > function的地图,你在启动时初始化 - 你的函数调用然后变成类似map[enum]->func()

模板在这里工作得不好,因为你试图在运行时做出决定,而模板在编译时做他们的事情。

一句话:继承

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 */
    }
}

然后,无论你想在哪里调用初始化,只需确保有一个指针或多态的引用才能正常工作:

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();

使用由枚举值索引的查找表(假设所有函数具有相同的签名),即:

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; 
} 

尝试一下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;
}

如果这个初始化确实是唯一的区别,那么我不确定任何其他成语会改善这种情况。

你可以从Tree继承并创建正确的树对象...但是你仍然需要区分哪一个实例化,所以你仍然会在某个地方找到类似的if / else块。

也就是说,如果不仅仅是初始化不同,你应该继承并使用虚函数来实现它们之间的差异。

以及您在标记中指出的模板方式:

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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM