【问题标题】:How to use templates instead of macros to create a class with a dynamic number of functions如何使用模板而不是宏来创建具有动态数量的函数的类
【发布时间】:2012-04-26 09:06:52
【问题描述】:

目前我正在创建一个带有 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;
}

【问题讨论】:

  • 模板不能替代宏,它们的用途完全不同。
  • 在构造函数/方法声明之后不需要分号 (;)。
  • 通过模板你只能设置你的类成员/函数的类型。您不能设置名称。所以答案是:你不能通过模板来做到这一点。
  • 与您的问题无关:我认为您不仅可以创建许多成员变量 protected 还可以使用公共 getter 和 setter 访问的设计是非常值得怀疑的。基本上没有封装,你也可以继承struct 有两个公共字段。
  • 这里的一个关键点是类模板不能包含名称是令牌粘贴结果的成员(NrA_ 和set_NrA)。模板可以将类型作为模板参数,但不能像宏那样使用一系列标记。所以你不能简单地使用模板来重现这些宏。

标签: c++ function templates dynamic macros


【解决方案1】:

尽管宏不是 C++ 的最大特性,但由于范围问题、调试限制和其他可能的意外,它们确实偶尔使用。由于宏是文本替换器,它们的优势之一是可以使用文本输入创建代码,如您的示例中所做的那样。

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

所以,正如 Gumik 已经评论的那样,我不明白如何使用模板来做到这一点。

【讨论】:

    【解决方案2】:

    您可以使用模板 mixin 组合不同类型的 setter 和 getter。模板混合定义了一个从其模板参数继承的类。这是您使用 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++) 中获得更好的错误消息。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我建议你看一看《现代 C++ 设计: Generic Programming and Design Patterns Applied”。特别是“PolicyBased Class Design”一章可能会给你一些想法。 不过,我不知道它是否符合您的确切需求。

        【讨论】:

          猜你喜欢
          • 2017-11-21
          • 1970-01-01
          • 2021-06-02
          • 2020-01-05
          • 1970-01-01
          • 1970-01-01
          • 2012-09-05
          • 1970-01-01
          • 2021-08-14
          相关资源
          最近更新 更多