C ++:私有结构的每个单个成员的通用getter/setter
Posted
技术标签:
【中文标题】C ++:私有结构的每个单个成员的通用getter/setter【英文标题】:C++ : generic getter/setter for each single member of private struct 【发布时间】:2016-08-12 19:43:48 【问题描述】:可能是常见的,但在这里找不到任何现有主题。
所以我有一个带有许多成员的私有结构的类。我想为单个成员编写 getter 和 setter,但是为每个成员编写一个 getter/setter 会很长且重复...如何轻松通用?
class C
public:
typedef struct S
int a, b, c, d, e, f, g, h;
S;
void setS(S new_struct);
S getS();
void setSElement(????, int value);
int getSElement(????);
private:
S data;
用什么来代替?????? with 直接引用我想要的 S 的哪个元素(a 到 h)?
不用说,我需要结构体保持结构体而不与我的其他班级成员混在一起,而且我还需要能够一次完全地获取/设置结构体。
提前致谢,
查尔斯
【问题讨论】:
也许并不总是,但如果你想要这样的东西,设计中通常会有问题。 为什么S
是私有的,如果你为这个成员提供getter/setter 抛出C
?
为什么不使用数组来代替,所以你为????
提供索引。
1) 为什么 private + get/set :因为需要在 getter/setter 中进行大量检查和转换(检查值一致性,从度数转换为弧度,检查单位一致性和执行其他转换需要时...),但我不希望用户担心
2) 为什么不使用数组:因为我希望 S 的成员有明确的名称,它们都有非常不同的含义,而不仅仅是序列中的相似元素
【参考方案1】:
#include <stdio.h>
#include <cstddef>
class C
public:
typedef struct S
int a, b, c, d, e, f, g, h;
S;
inline void setSElement(std::size_t offset, int value)
*(int*)((C::S*)&data + offset) = value;
inline int getSElement(std::size_t offset)
return *(int*)((C::S*)&data + offset);
private:
S data;
;
int main(int argc, char const* argv[])
C c;
c.setSElement(offsetof(C::S, a), 20);
printf("a = %d\n", c.getSElement(offsetof(C::S, a)));
return 0;
通过宏的简写方法:
#define SET_S(__e__) inline void setSElement_ ## __e__ (int value) setSElement(offsetof(C::S, __e__), value);
#define GET_S(__e__) inline int getSElement_ ## __e__ () getSElement(offsetof(C::S, __e__));
SET_S(a)
GET_S(a)
用法:
C c;
c.setSElement_a(30);
printf("a = %d\n", c.getSElement_a());
【讨论】:
【参考方案2】:enum
和std::array
可以这样使用,
class C
public:
std::array<int, 3> Elems;
enum class index a, b, c;
void setElements(const std::array<int, 3>& elems) Elems = elems;
std::array<int, 3> getElements() const return Elems;
void setElemAtIndex(index at, int value)
Elems[static_cast<int>(at)] = value;
int getElemAtIndex(index at) const
return Elems[static_cast<int>(at)];
;
并且可以像这样使用;
C obj;
obj.setElements(std::array<int, 3>1, 2, 3);
auto elems = obj.getElements();
obj.setElemAtIndex(C::index::c, 30);
auto a = obj.getElemAtIndex(C::index::c);
【讨论】:
【参考方案3】:根据您的要求,您似乎需要一些枚举:
class C
public:
enum class EIndex A, B, C, D, E, F, G, H;
struct S
int get(EIndex) const;
int& get(EIndex);
int a, b, c, d, e, f, g, h;
;
void setS(const S& new_data) data = new_data
const S& getS() const return data;
void setSElement(EIndex index, int value) data.get(index) = value;
int getSElement(EIndex index) return data.get(index);
private:
S data;
int C::S::get(EIndex index) const
const int array[] = a, b, c, d, e, f, g, h;
return array[static_cast<int>(index)];
int& C::S::get(EIndex index)
int* array[] = &a, &b, &c, &d, &e, &f, &g, &h;
return *array[static_cast<int>(index)];
【讨论】:
【参考方案4】:用一个函数设置S
的特定数据成员
你可以使用这样的界面:
void setSElement(int S::*field, int val)
data.*field = val;
int getSElement(int S::*field) const
return data.*field;
你可以这样使用它:
C c;
c.setSElement(&C::S::a, 17);
c.setSElement(&C::S::b, 16);
std::cout << c.getSElement(&C::S::a) << "\n";
顺便说一句,在 C++ 中你不需要这样的 C 方式组合:typedef struct S S
,你可以写 struct S
。
【讨论】:
【参考方案5】:如果您的动机是,那么这是一个坏主意,但是为每个成员编写一个 getter/setter 会很长且重复......。
C
的用户为每个成员指定明确的名称很有用。几乎所有支持 OOP 的语言都是这样设计的。也许 smalltalk 是个例外。
您还提到您必须对设置器进行验证。 setSElement
函数很快就会变得复杂。
如果您想保持函数调用的类型安全,您将获得更多代码来实现这一点。
话虽这么说,如果你想要什么建议????可能是,一个简单的枚举就可以了。
class C
public:
enum SElement a, b ...
setSElement(SElement member, int value);
【讨论】:
以上是关于C ++:私有结构的每个单个成员的通用getter/setter的主要内容,如果未能解决你的问题,请参考以下文章