创建宏来为任何c++类生成getter

Create macro to generate getters for any class c++

本文关键字:getter c++ 任何 创建      更新时间:2024-09-26

最近,我开始思考如何通过通用类/函数的名称来通用对私有数据成员的访问。原因是我有很多私人成员,为每个成员创建一个getter很麻烦。我尝试使用预处理器宏来完成以下

#define RETURNS(...) -> decltype((__VA_ARGS__))  { return (__VA_ARGS__); }
#define GET(classname, name, funcname) auto funcname() RETURNS(classname->name);
class foo {
private: 
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
foo() = default;
~foo() = default;
GET(this, a, getter);
};
int main(const int argc, char* argv[]) {
foo obj;
std::cout << obj.getter();
return 0;
}

这一个是编译的,但有没有一种方法可以在foo中创建一个getter,它在运行时使用变量的名称并返回this->(name)?使用这种方法,我可以减少引入getter的代码,尽管数据成员越多,我需要的getter就越多,但我希望有一个getter可以按名称访问任何数据成员。你对如何做有什么建议吗?我正在寻找这样的语法:

#define RETURNS(...) -> decltype((__VA_ARGS__))  { return (__VA_ARGS__); }
#define GET(classname, name) RETURNS(classname->name);
class foo {
private: 
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
foo() = default;
~foo() = default;
auto getter(auto x) GET(this, x);
};

这里x是我输入的名称,abc

你对如何做到这一点有什么建议吗?

为什么所有的decltype->以及带有__VA_ARGS__RETURNS的可变宏。。。只是:

#include <vector>
#include <string>
#define DECL_GETTER(name) 
auto get_##name() { return this->name; }
class foo {
private: 
int a = 1;
std::vector<int> b = std::vector<int>(3, 1);
std::string c = "pika-chuuu";
public:
DECL_GETTER(a)
DECL_GETTER(b)
DECL_GETTER(c)
};
int main() {
foo f;
f.get_a();
f.get_b();
f.get_c();
}

我也会添加const过载。

你可能想研究QT属性系统,这基本上是一个更高级的版本。

主观:TBH有了这样一个宏,你就在不需要它们的地方进行抽象。值得花时间吗?它用不明显的宏隐藏了一些明显的代码,使得IDE"跳转到定义";更难,使维护和推理变得更加困难。使用IDE功能重命名变量将更加困难。考虑一下逐字逐句地手工编写这些getter——考虑一下可读清晰的代码,这在第一眼就很明显,即使你不得不牺牲一点重复,并键入更多的() { return字符。配置您的IDE,这样您就可以拥有";为这个成员函数创建一个getter/setter;加速开发的操作(例如,请参阅QTCreator,这是一个非常好的功能(。

有没有一种方法可以在foo中创建一个getter,它在运行时使用变量的名称并返回这个->(姓名(?

C++是一种没有反射的语言,所以基本上没有,或者它需要比实际更多的样板代码。

修订:

正如@HolyBlackCat所提到的,不需要堆分配,应该直接使用impl类作为对象:

class foo{
struct foo_data
{
int i;
std::string s;
};
foo_data data;
public:
template<typename ... Args>
foo(Args&& ... args)
: data(std::forward<Args>(args)...)
{}
foo_data const* operator->() const   // Returns a pointer to const data
{
return &data;
}
};

然后访问数据:

int main()
{
auto f = foo(3, "hello");
std::cout << f->i << f->s;          // Accessing data, prints: "3hello"
// f->i += 1;                       // Error: assignment of member in read-only object
}