如何重载运算符以在 operator[] 调用中调用 setter 函数?

How to overload the operators to call a setter function on an operator[] call?

如何重载 class 的运算符,以便使用

的语法
classInstance[index] = value;

执行

classInstance.cfgfile.Write(index,value)

背景资料;随意跳过。

我们开发的应用程序使用内存映射访问一段 NVRAM - 实际上,映射的只是两个寄存器,地址和数据。您写入地址寄存器,然后写入或读取数据寄存器。初始化后,读取和写入由 class 的简单 [] 重载执行,该 class 持有对内存段的引用。你引用实例的 [] 给出你想要读写的单元格的命名空间索引,它会做它的事情。

int& IndirectMemory::operator[](RTCMemIndex idx)
{
    *midx_reg = idx;
    return *mdata_reg;
}

(代码中删除了不相关的元素,如互斥锁和健全性检查)。

一切正常...只要 NVRAM 正常工作。这个特定的芯片已经停产,'out in the wild' 目前已经开始老化。它们的功能对我们的使用意义不大,如果芯片损坏,我们可以将它们的角色转移到闪存而几乎没有影响(只是闪存磨损多一点)。事情是我们想使用我们的配置格式的闪存记录,它使用 getter 和 setter。

int TCfgFile::ReadKey(std::string Key);
void TCfgFile::WriteKey(std::string Key,int data);

在代码的许多地方,我们通过 IndirectMemory[Some_Register] = Some_Value; 写入各种经常更改的内容来调用 NVRAM,我们希望通过重启来保持。我想保留此语法和行为,但如果检测到 NVRAM 已损坏或通过配置条目手动禁用,则能够写入文件。


网络上充斥着使用 operator[] 仅通过 return 引用它来设置给定值的示例。对于 example:

unsigned long operator [](int i) const    {return registers[i];}
unsigned long & operator [](int i) {return registers[i];}

在这种情况下,如果我调用 reg[3] = 1;[] 将 return 引用元素#3,默认 operator= 将写入参考就好。

但由于我无法 return 对文件中的键的引用(.WriteKey() 只执行完整的写入,return 成功或错误),并且 operator= 不带索引,恐怕这个简单的选项不会有帮助。

您可以使用代理 class 来解决这个问题。由于 value 不能传递到 classInstance 我们需要创建一个对象 operator[] 可以 return 它将获得 value 的值并知道哪个实例将操作应用到。使用

struct Proxy
{
    classInstance_type& to_apply;
    index_type index;
    Proxy(classInstance_type& to_apply, index_type index) : to_apply(to_apply), index(index) {}
    Proxy& operator=(value_type const & value)
    {
        to_apply.cfgfile.Write(index,value)
        return *this;
    }
};

你的class的operator[]看起来像

Proxy operator[](index_type index)
{
    return Proxy{*this, index};
}

然后当您执行 classInstance[index] = value; 时,您调用 Proxyoperator=,它具有对要调用的对象的引用、要使用的索引以及您还需要的值.

您也可以在没有代理的情况下执行此操作 class。您可以使 operator[] return 成为对 *this 的引用,然后重载所述 class 的 = 运算符以对提供给的任何内容执行 Write operator= 在第二个参数中。

#include <iostream>

struct Foo {
    void Write(int idx, int value) {
        std::cout << "Write(" << idx << ", " << value << ")\n";
    }

    Foo& operator[](int idx) {
        this->index = idx;
        return *this;
    }
    void operator=(int value) {
        this->Write(this->index, value);
    }

    int index;
};

int main() {
    Foo f;
    f[5] = 10;
}

打印:Write(5, 10)