今天早上我读了The Pragmatic Programmer第三章关于每个程序员应该拥有的基本工具的书,他们提到了代码生成工具。他们提到了一个用于C++程序的Perl脚本,该脚本有助于自动化私有数据成员的get/set()成员函数的实现过程。
有人知道这样的脚本吗?在哪里可以找到它?我一直无法想出正确的谷歌关键词来找到它。
发布于 2009-05-04 16:40:47
尽管它没有直接回答您的问题,但您可能会发现,在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先生在注释中指出的那样,类作者稍后可以在不修改类的逻辑结构的情况下更改实现(例如,通过用一对x()方法替换property<int> x成员),尽管二进制兼容性会丢失,因此无论何时进行这样的更改,用户都需要重新编译他们的客户端代码。这种轻松地合并未来更改的能力实际上是人们最初使用getter/setter函数而不是公共成员的主要原因。
性能说明:因为我们使用CRTP来实现“编译时多态性”,所以在子类中提供您自己的check()没有虚拟调用开销,并且您不需要将其声明为virtual。
发布于 2009-05-04 15:29:24
由于大多数C++私有成员不应该通过Get/Set样式函数访问,这似乎不是一个好主意。
有关原因的简单示例,请考虑C++ std::string类。它的私有成员可能看起来像这样(确切的实现并不重要):
private:
int last, len;
char * data;你认为为它们提供get/set成员有什么意义吗?
发布于 2009-05-04 16:14:50
我不能帮你找到那个特定脚本的位置。但是,代码生成工具也有quite a lot。你甚至可能已经在你的IDE中找到了你想要的东西。有关如何、为什么以及是否使用代码生成工具的更多争论/输入,您可以查看this stackoverflow question。我喜欢这个问题的公认答案。
https://stackoverflow.com/questions/820569
复制相似问题