You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++如何重载下标运算符以实现多类型键值对存取

实现支持多类型键值对的下标运算符重载

你需要用vector存储键值对(如"Pi = 3.14159"、"UserName = Bob"),值支持string、bool、int、float、double类型,希望通过以下形式操作:

Foo f; f["Pi"].SetFloat(3.14159);          // 添加浮点型键值对
float myFloat = f["Pi"].GetFloat();        // 获取浮点型值

Foo f; f["UserName"].SetStr("Bob");        // 添加字符串型键值对
const char * name = f["UserName"].GetStr();// 获取字符串值

现有代码中,你不知道如何重载下标运算符[],当前框架如下:

Foo & operator[]( const char * pszKey ){
   // 此处不知如何实现
}

要求该重载支持查找键、添加键值对或返回对应值的功能,需要示例代码理解实现方式。

你的现有部分代码如下:

const char * va( const char * fmt, ... ) { // va = "VarArgs"
  // 将值格式化为字符串
}

void Foo::SetString( const char * Key, const char * ) { // 私有方法
   // 将键值对添加至vector
}

const char * Foo::GetString( const char * key ) {  // 私有方法
   // 查找键并返回对应值
}

// 省略部分代码...

const char * Foo::GetStr( const char* Key ) {
  // 实现细节
}
void Foo::SetStr( const char * Key, const int Value ) {
   SetStr( Key, va("%i", Value ));
}

float Foo::GetFloat( const char * Key ) {
   return (float) atof( GetStr( Key ));
}
void Foo::SetFloat( const char * Key, float Value ) {
  // 实现细节
}

void Foo::SetInt( const char* Key, int Value );
int Foo::GetInt(const char* Key);

void Foo::SetBool( const char* Key, bool Value ); 
bool Foo::GetBool(const char* Key);

实现思路

你需要一个代理类(比如FooProxy),让operator[]返回这个代理对象,而非Foo&。代理对象持有目标Foo实例的引用和键名,这样就能在代理类的SetXxx/GetXxx方法中调用Foo的对应私有方法,完成键值对的操作。

完整示例代码

#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>

// 先声明Foo类,因为代理类需要引用它
class Foo;

// 代理类:承接operator[]的返回值,实现链式调用
class FooProxy {
private:
    Foo& m_foo;
    const char* m_key;
public:
    FooProxy(Foo& foo, const char* key) : m_foo(foo), m_key(key) {}

    // 各种Set方法,转发给Foo的对应方法
    void SetStr(const char* value) {
        m_foo.SetString(m_key, value);
    }

    void SetInt(int value) {
        m_foo.SetInt(m_key, value);
    }

    void SetFloat(float value) {
        m_foo.SetFloat(m_key, value);
    }

    void SetBool(bool value) {
        m_foo.SetBool(m_key, value);
    }

    // 各种Get方法,转发给Foo的对应方法
    const char* GetStr() {
        return m_foo.GetStr(m_key);
    }

    int GetInt() {
        return m_foo.GetInt(m_key);
    }

    float GetFloat() {
        return m_foo.GetFloat(m_key);
    }

    bool GetBool() {
        return m_foo.GetBool(m_key);
    }
};

// 键值对结构体,存储在vector中
struct KeyValuePair {
    std::string key;
    std::string value;

    KeyValuePair(const char* k, const char* v) : key(k), value(v) {}
};

class Foo {
private:
    std::vector<KeyValuePair> m_kvPairs;

    // 私有方法:查找键对应的索引,找不到返回-1
    int findKeyIndex(const char* key) const {
        for (size_t i = 0; i < m_kvPairs.size(); ++i) {
            if (m_kvPairs[i].key == key) {
                return static_cast<int>(i);
            }
        }
        return -1;
    }

    // 实现私有SetString方法
    void SetString(const char* Key, const char* value) {
        int idx = findKeyIndex(Key);
        if (idx != -1) {
            // 键存在,更新值
            m_kvPairs[idx].value = value;
        } else {
            // 键不存在,添加新键值对
            m_kvPairs.emplace_back(Key, value);
        }
    }

    // 实现私有GetString方法
    const char* GetString(const char* key) const {
        int idx = findKeyIndex(key);
        if (idx != -1) {
            return m_kvPairs[idx].value.c_str();
        }
        // 找不到返回空字符串(可根据需求修改错误处理逻辑)
        return "";
    }

    // 实现va函数(示例)
    static const char* va(const char* fmt, ...) {
        static char buffer[256];
        va_list args;
        va_start(args, fmt);
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        va_end(args);
        return buffer;
    }

public:
    // 重载[]运算符,返回代理对象
    FooProxy operator[](const char* pszKey) {
        return FooProxy(*this, pszKey);
    }

    // 公开的Get/Set方法,供代理类调用
    const char* GetStr(const char* Key) {
        return GetString(Key);
    }

    void SetStr(const char* Key, const char* Value) {
        SetString(Key, Value);
    }

    void SetStr(const char* Key, int Value) {
        SetString(Key, va("%i", Value));
    }

    float GetFloat(const char* Key) {
        return static_cast<float>(atof(GetString(Key)));
    }

    void SetFloat(const char* Key, float Value) {
        SetString(Key, va("%.6f", Value));
    }

    int GetInt(const char* Key) {
        return atoi(GetString(Key));
    }

    void SetInt(const char* Key, int Value) {
        SetString(Key, va("%i", Value));
    }

    bool GetBool(const char* Key) {
        const char* val = GetString(Key);
        return (val[0] == '1' || val[0] == 't' || val[0] == 'T');
    }

    void SetBool(const char* Key, bool Value) {
        SetString(Key, Value ? "true" : "false");
    }
};

// 测试代码
int main() {
    Foo f;
    f["Pi"].SetFloat(3.14159f);
    printf("Pi = %.5f\n", f["Pi"].GetFloat());

    f["UserName"].SetStr("Bob");
    printf("UserName = %s\n", f["UserName"].GetStr());

    f["Age"].SetInt(25);
    printf("Age = %d\n", f["Age"].GetInt());

    f["IsActive"].SetBool(true);
    printf("IsActive = %s\n", f["IsActive"].GetBool() ? "true" : "false");

    return 0;
}

关键说明

  1. 代理类FooProxy:作为operator[]的返回值,持有Foo的引用和键名,把SetXxx/GetXxx的调用转发给Foo的对应方法,完美实现你要的链式调用语法。
  2. operator[]实现:不需要返回Foo&,直接返回一个FooProxy对象,携带当前的键名和Foo实例引用即可。
  3. 键值对存储:用vector<KeyValuePair>管理,findKeyIndex方法负责查找键的位置,实现更新/添加逻辑。
  4. 类型转换:所有类型最终都转成字符串存储在vector中,获取时再转成对应类型,和你现有代码的思路保持一致。

内容的提问来源于stack exchange,提问作者Ariana_N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:35:36