是否有一个Perl脚本来实现C ++类的get / set成员函数?

时间:2009-05-04 15:25:01

标签: c++ perl code-generation

今天早上我正在阅读每本程序员应该拥有的The Pragmatic Programmer第3章“基本工具”这本书,他们提到了代码生成工具。 他们提到了一个用于C ++程序的Perl脚本,它帮助自动化为私有数据成员实现get / set()成员函数的过程。

有没有人知道这样的脚本以及在哪里找到它?我一直无法找到合适的谷歌关键字来找到它。

5 个答案:

答案 0 :(得分:9)

虽然它没有直接回答您的问题,但您可能会发现生成的代码对于管理C ++中的属性实际上是不必要的。以下模板代码将允许您方便地声明和使用属性:

// Declare your class containing a few properties
class my_class {
public:
    property<int> x;
    property<string> y;
    ...
};

...

my_class obj;
cout << obj.x();          // Get
obj.y("Hello, world!");   // Set

以下是代码:

// Utility template to choose the 2nd type if the 1st is void
template <typename T, typename U>
struct replace_void {
    typedef T type;
};

template <typename T>
struct replace_void<void, T> {
    typedef T type;
};

// Getter/setter template
template <typename T, typename D = void>
class property {
    typedef typename replace_void<D, property>::type derived_type;

    derived_type& derived() { return static_cast<derived_type&>(*this); }

public:
    property() {}   // May be safer to omit the default ctor
    explicit property(T const& v) : _v(v) {}
    property(property const& p) : _v(p._v) {}
    property& operator=(property const& p) { _v = p._v; return *this; }

    T operator()() const { return _v; }                 // Getter
    void operator()(T const& v) { derived().check(v); _v = v; }   // Setter

protected:
    // Default no-op check (derive to override)
    void check(T const& v) const { (void)v; //avoid unused variable warning}

private:
    T _v;
};

check()是一个测试被赋值是否有效的函数。您可以在子类中覆盖它:

class nonnegative_int : public property<int, nonnegative_int> {
public:
    // Have to redeclare all relevant ctors unfortunately :(
    nonnegative_int(int v) : property<int, nonnegative_int>(v) {}

    void check(int const& v) const {
        if (v < 0) {
            throw "Yikes! A negative integer!";
        }
    }
};

你有它 - 外部生成的getter / setter函数的所有优点,没有任何混乱! :)

您可以选择让check()返回表示有效性的bool,而不是抛出异常。您原则上可以添加一个类似的方法access(),用于捕获对该属性的读取引用。

编辑:正如Fooz先生在评论中指出的那样,类作者可以在不修改类的逻辑结构的情况下更改实现(例如,将property<int> x成员替换为一对x()方法),虽然二进制兼容性丢失,因此用户需要在进行此类更改时重新编译其客户端代码。 这种无痛地融入未来变化的能力实际上是人们首先使用getter / setter函数而不是公共成员的主要原因。

效果说明:因为我们使用CRTP来实现“编译时多态”,所以没有虚拟调用开销来提供自己的check()子类,您无需声明它virtual

答案 1 :(得分:3)

由于大多数C ++私有成员不应该通过Get / Set样式函数访问,这似乎是一个坏主意。

有关其原因的简单示例,请考虑C ++ std :: string类。它的私人成员可能看起来像这样(确切的实现并不重要):

private:
   int last, len;
   char * data;

你认为为那些提供获取/设置成员是否有意义?

答案 2 :(得分:2)

我无法帮助您了解该特定脚本的位置。但是,有quite a lot代码生成工具。您甚至可能已经将所需内容作为IDE的一部分。有关如何,为何以及是否使用代码生成工具的更多辩论/意见,您可以查看this stackoverflow question。我喜欢这个问题的接受答案。

答案 3 :(得分:2)

我知道有一位程序员uses Perl to augment the C preprocessor涉及到宏(latest version of that project)。基本的想法是你会决定一些约定来告诉你的Perl脚本何时生成一个getter或setter:

struct My_struct {
    //set
    //get
    int x;

    int y;

    //get
    int z;
};

考虑到这样的代码,我可以编写一个脚本来查找在成员变量声明之前在行上的注释“get”或“set”组成的注释行,然后用简单的setter / getters替换它们。在上面的例子中,我将在关联的成员变量定义之后生成void set_x(int i),int get_x()和int get_z()

警告:不要使用s ///就地执行此操作。相反,单独扫描每一行,如果你找到一个合适的注释行,将“我需要一个getter / setter”的东西推到一个堆栈上,那么当你看到相关的成员变量时,弹出堆栈并生成代码

细节中有一些恶魔,但总的来说就是这个想法。

答案 4 :(得分:2)

您希望脚本不加选择地为所有私有成员生成get / set函数吗?那不是一个非常有用的剧本;你可能不会在谷歌找到它。如果您希望能够以某种方式标记您的成员变量并为您自动生成getter和/或setter骨架,那么IDE宏似乎更合适。试试谷歌。