如何使用模板而不是宏来创建具有动态数量的函数的类

时间:2012-04-26 09:06:52

标签: c++ function templates dynamic macros

目前我正在创建一个带有set和get函数的基类。 但我想添加更复杂的宏,但宏对于调试非常糟糕,所以我想用模板做,但我不知道有人知道我的书或链接。

我真正的问题要复杂得多,我只是创建了一个集合,并举例说明问题。

作为一个简单的例子,请参阅:

#include <iostream>

#define SETGET_BEGIN(name) \
  class name##Base { \
  public: name##Base(){};

#define SETGET_VAR(type,name) \
  protected: type name##_; \
  public: void set##name(const type &_r) {name##_ = _r;} ; \
  public: const type &get##name() const {return name##_; };  \

#define SETGET_END };

SETGET_BEGIN(MyClass)
SETGET_VAR(int,NrA)
SETGET_VAR(float,NrB)
SETGET_END

class MyClass : public MyClassBase {
  public: 
    MyClass() : MyClassBase() {};
};

int main(int argc, char **argv) {
    MyClass myclass;
    myclass.setNrA(4);    
    return 0;
}

4 个答案:

答案 0 :(得分:3)

即使宏不是C ++的最大特性,但由于范围问题,调试限制和其他可能的意外,它们偶尔也会使用。他们的优势之一,因为宏是文本替换者,可以使用文本输入创建代码,如您的示例所示。

我没有看到制作“动态”类的方法的附加价值,但类似的方法可用于枚举值或其他重复代码的序列化或值检查。宏也可以用于记录以获取文件名/ linenumber / functionname /...

所以,正如Gumik已经评论过的那样,我看不出你如何用模板做到这一点。

答案 1 :(得分:1)

您可以使用模板mixin组合不同类型的setter和getter。模板mixins定义一个继承自其模板参数的类。以下是使用mixins而不是宏的示例:

class MyBaseClass {
public:
    MyBaseClass() {}
};

template<class B> class SetGetNrA : public B {
private:
    int NrA;
public:
    void setNrA(int NrA) { this->NrA = NrA; }
    int getNrA() { return NrA; }
};

template<class B> class SetGetNrB : public B {
private:
    float NrB;
public:
    void setNrB(float NrB) { this->NrB = NrB; }
    float getNrB() { return NrB; }
};

现在使用它:

typedef SetGetNrA<SetGetNrB<MyBaseClass> > MyClass;
MyClass myclass;
myclass.setNrA(4);

您也可以将变量的类型设置为模板参数,但如果您希望变量的名称是参数,则必须使用宏。尽管如此,在模板中完成更多工作可以确保您从一个好的编译器(clang ++)获得比仅使用宏替换更好的错误消息。

答案 2 :(得分:0)

最简单的解决方案是std::tuple。它包含您需要的所有功能,名称除外。元组方法不是setnrA(int),而是set<1>(int)。显然你可以添加一个枚举来为元组索引分配有意义的名字,这样你就可以调用.set<nrA>(4)

答案 3 :(得分:0)

我建议你看看“现代C ++设计: 应用的通用编程和设计模式“。具体而言,”基于策略的类设计“一章可能会给你一些想法。 不过,我不知道它是否符合您的确切需求。