C ++中的属性实现

大家好! 在实施项目时,开发人员通常需要仅包含字段且没有任何功能的类。 这样的类可用于存储必需的信息及其后续操作。

实现此类的第一种方法是基于C结构的使用。 这种方法的缺点是,所有字段都是可写和可读的,并不总是很好。

struct person { int id; human type; std::string name; std::string address[5]; bool merried; }; 

第二种方法基于隐藏所有字段并为字段提供获取器和设置器。 Java语言生动地使用了这种方法。 作为优势,我们可以控制对字段的访问。 缺点包括这样一个事实,即类变得很大,并且吸气剂和吸气剂没有逻辑上的负担。

 class person { public: void set_id(int id) { this->id = id; } int get_id() const { return id; } void set_merried(bool merried) { this->merried = merried; } bool is_merried() const { return merried; } void set_type(human type) { this->type = type; } human get_type() const { return type; } void set_name(const std::string& name) { this->name = name; } const std::string& get_name() const { return name; } private: int id; human type; std::string name; std::string address[5]; bool merried; }; 

如果字段是类类型,则有时需要通过值,左值链接,右值链接设置对象。 并且还使用了const / volatile修饰符。

 class person { public: void set_name(const std::string& name) { this->name = name; } void set_name(std::string&& name) { this->name = std::move(name); } const std::string& get_name() const { return name; } private: int id; human type; std::string name; std::string address[5]; bool merried; }; 

许多语言都将属性作为语言功能来支持。 编写代码变得更加干净和可靠。 为了简化getter和setter的编写,可以使用宏来生成代码。

 #define SETTER_PRIM(type, name) \ void set_##name(type value) { \ this->name = value; \ } #define GETTER_PRIM(type, name) \ type get_##name() const { \ return name; \ } 

但是使用宏很危险。 我们可能没有正确指出类型(类型)或类型(名称)错误的变量。 最好的情况是,使用getter和setter时会出现运行时错误。 在最坏的情况下,错误仍然存​​在。

我希望我们能够生成getter和setter,但是同时我们可以检查类型的正确性,带有变量(名称)的类型的正确性以及类型是否相等。 这可以使用type_traits标准库从C ++ 11开始进行。

 #define SETTER_PRIM(type, name) \ void set_##name(type value) { \ using T1 = type; \ using T2 = decltype(name); \ static_assert(std::is_fundamental<T1>::value, \ "only primitive types"); \ static_assert(std::is_fundamental<T2>::value, \ "variable must be primitive"); \ static_assert(std::is_same<T1, T2>::value, \ "both types must be same"); \ this->name = value; \ } #define GETTER_PRIM(type, name) \ type get_##name() const { \ using T1 = type; \ using T2 = decltype(name); \ static_assert(std::is_fundamental<T1>::value, \ "only primitive types"); \ static_assert(std::is_fundamental<T2>::value, \ "variable must be primitive"); \ static_assert(std::is_same<T1, T2>::value, \ "both types must be same"); \ return name; \ } 

使用这种方法,您可以为所有类型的类字段实现getter和setter。

  • 基本类型
  • 对象类型
  • 转移
  • 数组
  • 指针
  • 连结

用于getter和setter的所有宏都以仅标头库的形式实现。 通过仅连接一个头文件,您可以轻松地使用所有必需的getter和setter来实现日期类。

 #include "property.hpp" class person { public: person() = default; ~person() = default; SETTER_PRIM(int, id); SETTER_FLAG(bool, merried); SETTER_ENUM(human, type); SETTER_PTR(int, next); SETTER_ARR(std::string, address, 3); SETTER_OBJ_LR(std::string, name); SETTER_OBJ_CLR(std::string, name); SETTER_OBJ_RR(std::string, name); GETTER_PRIM(int, id); GETTER_FLAG(bool, merried); GETTER_ENUM(human, type); GETTER_OBJ_LR(std::string, name); GETTER_OBJ_CLR(std::string, name); GETTER_PTR(int, next); GETTER_ARR(std::string, address); private: int id; human type; std::string name; std::string address[5]; bool merried; int* next; }; 

可以在此链接中查看开放源代码库的源代码。

Source: https://habr.com/ru/post/zh-CN459212/


All Articles