Simple C++ getter/setters
Simple C++ getter/setters
最近我把getter和setter写成(注意:真正的类在getter/setter中做更多的事情):
struct A {
const int& value() const { return value_; } // getter
int& value() { return value_; } // getter/setter
private:
int value_;
};
它允许我做以下操作:
auto a = A{2}; // non-const object a
// create copies by "default" (value always returns a ref!):
int b = a.value(); // b = 2, is a copy of value :)
auto c = a.value(); // c = 2, is a copy of value :)
// create references explicitly:
auto& d = a.value(); // d is a ref to a.value_ :)
decltype(a.value()) e = a.value(); // e is a ref to a.value_ :)
a.value() = 3; // sets a.value_ = 3 :)
cout << b << " " << c << " " << d << " " << e << endl; // 2 2 3 3
const auto ca = A{1};
const auto& f = ca.value(); // f is a const ref to ca.value_ :)
auto& g = ca.value(); // no compiler error! :(
// g = 4; // compiler error :)
decltype(ca.value()) h = ca.value(); // h is a const ref to ca.value_ :)
//ca.value() = 2; // compiler error! :)
cout << f << " " << g << " " << h << endl; // 1 1 1
这种方法不允许我:
- 验证设置器的输入(这是一个大BUT)
- 按const成员函数中的值返回(因为我希望编译器捕获对const对象的赋值:
ca.value() = 2
)。更新:请参阅下面的cluracan答案
然而,我仍然经常使用这个,因为
- 大多数时候我不需要
- 这使我能够将类的实现细节与其接口解耦,这正是我想要的
示例:
struct A {
const int& value(const std::size_t i) const { return values_[i]; }
int& value(const std::size_t i) { return values_[i]; }
private:
std::vector<int> values_;
// Storing the values in a vector/list/etc is an implementation detail.
// - I can validate the index, but not the value :(
// - I can change the type of values, without affecting clients :)
};
现在回答问题:
- 这种方法还有其他我没有看到的缺点吗
- 为什么人们更喜欢:
- 不同名称的getter/setters方法
- 将值作为参数传递?只是为了验证输入,还是有其他主要原因
- 通常,使用访问器/赋值器是一种设计气味,表明类的公共接口是不完整的。通常来说,你想要一个有用的公共接口,它提供有意义的功能,而不是简单地获取/设置(这比我们在C中使用结构和函数要好一两步)。每次你想写一个赋值函数,很多时候你想先写一个访问器,只要退一步问问自己
"do I *really* need this?"
- 仅仅是习惯用法方面的人可能还没有准备好期待这样的函数,所以这会增加维护人员对代码的开发时间
- 相同命名的方法与公共成员几乎相同:在这种情况下只需使用公共成员即可。当这些方法做两件不同的事情时,请将它们命名为两个不同的事情
- 通过非常数引用返回的"mutator"将允许出现各种各样的别名问题,即有人将别名隐藏到成员中,并依靠它在以后存在。通过使用单独的setter函数,可以防止人们对您的私人数据进行别名处理
这种方法不允许我:
- 按const成员函数中的值返回(因为我希望编译器捕获对const对象ca.value()=2的赋值)
我不明白你的意思。如果你的意思是我认为你的意思,你会感到惊喜:)试着让const成员按值返回,看看你是否可以执行ca.value()=2
。。。
但我的主要问题是,如果你想要某种输入验证,为什么不使用专用的setter和专用的getter 呢
struct A {
int value() const { return value_; } // getter
void value(int v) { value_=v; } // setter
private:
int value_;
};
它甚至可以减少打字量!(一个'=')。唯一的缺点是你不能通过引用一个修改它的函数来传递这个值
关于编辑后的第二个示例,使用vector
,使用getter/setter比原始示例更有意义,因为您希望访问值(允许用户更改值),但不希望访问向量(您不希望用户能够更改向量的大小)。
因此,尽管在第一个例子中,我真的建议公开成员,但在第二个例子中这显然不是一个选项,如果不需要输入验证,那么使用这种形式的getters/ssetters确实是一个不错的选择。
此外,当我有像您的第二种类型(带有向量)这样的类时,我喜欢访问begin
和end
迭代器。这允许使用标准工具更灵活地使用数据(同时仍然不允许用户更改vector
大小,并允许轻松更改容器类型)
另一个好处是随机访问迭代器有一个operator[]
(像指针一样),所以你可以进行
vector<int>::iterator A::value_begin() {return values_.begin();}
vector<int>::const_iterator A::value_begin()const{return values_.begin();}
...
a.value_begin()[252]=3;
int b=a.value_begin()[4];
vector<int> c(a.value_begin(),a.value_end())
(尽管它可能已经够难看的了,除了这个之外,你还需要你的getter/setter)
关于输入验证:在您的示例中,赋值发生在调用代码中。如果要验证用户输入,则需要将要验证的值传递到结构对象中。这意味着您需要使用成员函数(方法)。例如,
struct A {
// getter
int& getValue() const { return value_; }
// setter
void setValue(const int& value) {
// validate value here
value_ = value;
}
private:
int value_;
};
顺便说一句,.NET属性是通过隐藏的方法来实现的。
- 如何通过 getter 函数删除矢量的元素?
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 如何为 C 型字符串数组编写 getter 和 setter?
- C++ Setter/Getter,cout 工作,printf 失败
- 指向成员函数的模板指针 - getter
- 使用 getter 访问成员变量C++
- 如何在节点插件中创建 getter?
- 即使有 0 个错误,Getter 似乎也会使程序崩溃
- 将值推送到 getter 函数调用的列表中时出现问题
- 为什么我的编译器在调用 const getter 函数时抛出"转换丢失(const)限定符"错误?
- 私有变量无法正常工作的C++getter方法(只有Java经验)
- 如何使用 getter 功能push_back列表?
- 常量和非常量 getter 具有相同的名称
- 不一定获得成员价值的 getter 方法?
- 在 c++ 中使用 getter 作为unordered_map会创建大小为 8 的无效读取
- Getter 和 Setter 用于类 C++ 中的数组元素
- 无法使用在子类中定义的虚拟getter实现基类
- C++什么时候是使用无默认构造函数与getter和setters与直接调用类中的变量的正确时机
- 提取特征.一个班级里有很多getter/setters正常吗?
- Simple C++ getter/setters