2

我有一个类,我想为其定义 [] 运算符。该类包含一个串行数据包(以及对所述数据包进行操作的相关函数)。我想让用户有能力做这样的事情......

MyClass packet;
uint8_t byte = packet[3];  // get third byte of packet

我想阻止用户这样做......

packet[3] = 0xAA;  // this breaks encapsulation for my class :(

我一直在寻找解决方案,我想知道这个声明是否就是我所需要的(以及我的 .cpp 中的相关代码):

const uint8_t operator[](const std::size_t index) const;

虽然我相当肯定这会奏效,但我仍然对我的方法有一些不确定性,我希望你们能帮助我解决我的问题。

  1. 简单地返回值而不是引用是否“可以”?我知道在我见过的所有示例中都返回了参考。返回一个值是否可以帮助我解决我不希望在操作左侧使用“[]”的事实?再说一遍, const 不会阻止这种情况吗?

  2. 即使在非常量对象上也会调用 const 函数吗?我见过一些例子,其中声明了运算符的 const 版本和运算符的非常量版本。non-const 允许写入,而 const 只允许读取,但仅对 const 对象调用。我的目标是让非常量对象也只能被读取。

  3. 有没有一种干净的方法可以从操作员那里传递错误?我的主要问题是请求的数据可能超出了我拥有的数据的范围。我见过的所有示例都使用了断言,但我并不一定希望程序在用户对操作员的调用引起某种欢闹的情况下崩溃。我也不一定会传回特殊代码,因为我传回的字节的任何值都可能是有效的。

一如既往,感谢您的帮助,因为我慢慢地(但肯定地)从 C 程序员到 OO C++ 向导的可怕转变。

4

2 回答 2

7
  1. 是的,对于像uint8_t. 您可以返回一个 const 引用,并且const确实会阻止任何人通过它进行写入。uint8_t但是对于像按值返回这样的小类型是一个更好的主意。请注意,顺便说一句,当按值返回时,您不再需要const返回类型。

    返回一个 const 引用,即使它很难防止修改,也使调用代码能够创建和存储潜在的长期引用和指向数组元素的指针,如

    const uint8_t *byte = &packet[3];
    

    如果这是不可取的,那么按值返回也会阻止该功能。

  2. 是的,const将为非常量对象调用函数的版本(假设您没有提供非常量版本)。

  3. 专门为此目的引入了例外。异常为错误情况提供了专门的反馈路径,而不会影响函数声明和规范(即,您不必为错误返回保留任何值,也不必为此目的引入任何参数)。

于 2013-07-06T21:46:56.287 回答
1

如果您按返回并使用

 packet[3] = 0xAA; 

编译器会给你一个错误,因为 packet[3] 不是可修改的左值,这意味着它不能出现在赋值的左侧。

如果您通过引用返回,则用户可以编辑所引用的任何内容。您可以使用const引用来禁止修改。

引用方法的优点是可以避免复制值,如果 operator[] 的返回值很大,这可以提高效率/空间。如果只希望 operator[] 的返回值存在一个副本,则必须使用 (const) 引用。

于 2013-07-06T21:48:11.717 回答