运行时类型推导和代码重复

时间:2018-03-13 19:11:12

标签: c++

我有一些由枚举器的值定义的类型,它们表示从文件读入的数据类型。我希望根据数据类型执行不同的处理工作流程,但这会导致大量代码重复:

#include <iostream>

enum dataType {
    type1,
    type2,
    type3
};

struct File {
    File(dataType type):type{type}{};
    dataType type;
};

void process_file(File file)
{
    if(file.type == dataType::type1){ std::cout << "Do work A" << std::endl; };
    if(file.type == dataType::type2){ std::cout << "Do work B" << std::endl; };
    if(file.type == dataType::type3){ std::cout << "Do work C" << std::endl; }; 
}


int main(){
    File file(dataType::type2);
    process_file(file);
    return 0;
}

我的主要问题是必须通过&#34来检查价值;如果&#34;或者转换声明。想象一下,有50种类型而不仅仅是3种,它变得非常繁琐,并且容易检查每一种类型。

有谁知道处理这个问题的方法?模板代码是显而易见的尝试,但我仍然坚持使用枚举器来确定类型,所以我没有想到模板代码在这里是可能的,至少我所做的尝试还没有成功的。

3 个答案:

答案 0 :(得分:2)

摆脱switch的典型方法是继承和虚函数:

struct File {
    virtual ~File() = default;
    virtual void process() = 0;
};

struct Type1File : public File {
    void process() override { std::cout << "Do work A" << std::endl; };
};
struct Type2File : public File {
    void process() override { std::cout << "Do work B" << std::endl; };
};

int main(){
    std::unique_ptr<File> file = std::make_unique<Type1File>();

    file->process();
    return 0;
}

答案 1 :(得分:1)

如何将SomeWorker对象注入文件类而不是具有类型数据成员?

class SomeWorker
{
    ...
    public:
        virtual void DoWork() = 0;
};

class SomeWorker1 : public SomeWorker
{
    ...
    public:
        void DoWork() override { std::cout << "Do work A" << std::endl;}
};

class SomeWorker2 : public SomeWorker
{
    ...
    public:
        void DoWork() override { std::cout << "Do work B" << std::endl;}
};

...

struct File {
    File(SomeWorker worker):someWorker{worker}{};
    SomeWorker someWorker;
};

int main(){
    SomeWorker2 someWorker;
    File file(someWorker);
    file.someWorker.DoWork();
    return 0;
}

显然,代码不完整,有虚拟析构函数要添加,需要改进的地方,但是你明白了......

答案 2 :(得分:1)

您可以将dataType作为模板参数传递。

#include <iostream>

enum class dataType {
    type1,
    type2,
    type3
};

template <dataType T>
struct File {};

void process_file(File<dataType::type1> file) {
    std::cout << "Do work A" << std::endl;
}

void process_file(File<dataType::type2> file) {
    std::cout << "Do work B" << std::endl;
}

void process_file(File<dataType::type3> file) {
    std::cout << "Do work C" << std::endl;
}


int main() {
    File<dataType::type1> file1;
    File<dataType::type2> file2;
    File<dataType::type3> file3;

    process_file(file1);
    process_file(file2);
    process_file(file3);
    return 0;
}

然而,您还需要适应File是模板的事实,因此将其传递给其他函数等。不再那么容易了。您可以将处理File的所有函数更改为模板,也可以将所有File变体赋予公共基类。

对于我来说,其他答案似乎更容易,更重要。自从你在问题中提到它以来,大部分都发布了这个。