我可以使用常量引用而不是 getter 函数吗?
Can I use const references instead of getter functions?
我只是想知道如果我只允许一个 const 引用变量,我是否可以绕过使用 getters,如下所示
#include <string>
class cTest
{
private:
int m_i;
std::string m_str;
public:
const int & i;
const std::string & str;
cTest(void)
: i(m_i)
, str(m_str)
{}
};
int main(int argc, char *argv[])
{
cTest o;
int i = o.i; // works
o.i += 5; // fails
o.str.clear(); // fails
return 0;
}
我想知道为什么人们似乎根本不这样做。我缺少一些严重的劣势吗?请提供优点和缺点列表,并在必要时进行更正。
优势:
- 通过
- 调用 getter 函数没有开销。
- 程序大小减小,因为功能较少。
- 我仍然可以修改类的内部,引用变量提供了一个抽象层。
弊:
- 我没有getter函数,而是一堆引用。这将增加对象大小。
- 用
const_cast
,人家可以搞砸私人成员,但这些人很淘气吧?
确实有一些严重的缺点(除了你还提到的第二个缺点,我也把它放在"严重"类别中(:
1(你需要提供一个(并因此维护(一个复制构造函数:编译器默认将不起作用。
2( 您需要提供一个赋值运算符:编译器默认值将不起作用。
3(仔细考虑实现移动语义。同样,编译器默认值将不起作用。
这三件事意味着您提出的const
参考反模式是无法启动的。别这样!
getter 函数的一个优点是,你可能在某个时间点 - 想要更改返回值 - 如果没有 getter 函数,你就无法做到这一点。这个场景实际上需要你返回非引用,这在 c++ 中不太常见。[编辑] 但使用移动语义而不是引用,这应该是可行的[/编辑]
您可能还想在 getter 函数中放置一个断点以了解谁在读取其值,您可能希望添加日志记录等。这称为封装。
getter 的另一个优点是,在调试版本中,您可以对返回的数据添加额外的检查/断言。
最后,编译器将内联您的 getter 函数,这将产生与您提出的代码类似的代码。
一些额外的缺点:
1(模板代码希望使用函数调用来获取值,即。 size()
,如果你把它改成const&variable,那么你将无法在某些模板中使用它。所以这是一个一致性问题。
如果你想避免getter和setter,使用const引用成员不是解决方案。
相反,您需要确保周围结构的常量正确性(这会自动为您提供对成员的常量访问权限(,并且只是让成员成为它们逻辑上需要的任何内容。
请务必阅读何时可以、应该或可以与公共数据成员切换 getter 和 setter。例如,请参阅此问题。请注意,如果您更改界面,则预示的setter/getter的优势是调用getter不会影响调用站点。现实似乎并非如此,例如,重构一个成员及其所有接入点对于任何有自尊心的C++代码编辑器来说都是一个微不足道的操作。
虽然有人可能会争论封装,但我更强烈地主张常量正确性,这减轻了对大量封装的需求,并且确实大大简化了代码。
- 如何通过 getter 函数删除矢量的元素?
- 将值推送到 getter 函数调用的列表中时出现问题
- 为什么我的编译器在调用 const getter 函数时抛出"转换丢失(const)限定符"错误?
- Getter 函数,用于在 2d 数组是类的数据成员时检索 2d 数组元素
- 使用 getter 函数时,C++ 无法检索正确的值
- 从头文件调用字符串getter函数
- Getter函数的构造正确性
- C++getter函数:常量和非常量
- 带有Getter函数的C++中出错
- C++getter函数返回0
- 使用指针访问类内部的getter函数
- 为实例变量(即对象)调用getter函数时实际发生的情况
- 类getter函数C++的奇怪输出
- 如何为指针类变量执行 setter 和 getter 函数
- C++ - 通过 getter 函数在单独的类中从对象指针映射访问成员函数
- 为 std::vector <struct>创建一个 getter 函数
- 我可以使用常量引用而不是 getter 函数吗?
- 使用getter函数传递引用参数时出现意外行为
- 使getter函数恒定的方法
- C++ - 在内部,在定义类的成员函数时,应该使用成员变量名还是其getter函数?