代码之家  ›  专栏  ›  技术社区  ›  Olivier Lalonde Danny

C++中的NoOB:如何做一个对象= >值的关联数组?

c++
  •  3
  • Olivier Lalonde Danny  · 技术社区  · 16 年前

    我正在尝试创建一个全局(singleton)类,它可以将任何类型的对象与整数值相关联。我想用一个 map<T*, int> 变量,但想知道是否还有其他方法可以做到这一点。

    更新:这是我班的一个原型。告诉我我做错了什么!它的编译和工作都很好,但我不确定是否能以更好的方式完成。例如, int addr = (int)&objectA; 看起来很难看。

    更新2: 我选择了像《食水者》所提议的继承方式。考虑到我正在努力实现的目标,这会容易得多。感谢大家的反馈!

    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    struct PortPin {
        int port;
        int pin;
    };
    
    class Carte {
      public:
        void associate(int object_address, int port, int pins);
        map<int, PortPin> map_;
    };
    
    void Carte::associate(int object_address, int port, int pins) {
        PortPin values = {port, pins};
        map_[object_address] = values;
    }
    
    class A {
        public:
        A() {}
    };
    
    class B {
        public:
        B() {}
    };
    
    void main() {
        Carte carte;
    
        A objectA;
        B objectB;
    
        int addr = (int)&objectA;
    
        carte.associate(addr, 2, 7);
    
        cout << "Port: " << carte.map_[addr].port 
            << " Pin: " << carte.map_[addr].pin;
    }
    
    3 回复  |  直到 16 年前
        1
  •  2
  •   Potatoswatter    16 年前

    您应该使用一个基类。

    struct PortPin {
        int port;
        int pin;
        bool is_valid;
    
        PortPin() { is_valid = false; }
    
        void associate( int in_port, int in_pin ) {
            port = in_port;
            pin = in_pin;
            is_valid = true;
        }
    };
    
    class A : public PortPin {
        public:
        A() {}
    };
    
    class B : public PortPin {
        public:
        B() {}
    };
    
    …
    
    A blah;
    A.associate(2,7);
    

    你要做的指针运算不是在水上跑动,而是在激流中跑动。

    能够与人交往并不那么重要 任何 对象。你打算把你的单身汉和一个端口号联系起来吗?总是从适当的基础派生每个类以获取所需的服务。

    如果您关心portpin库占用的内存(最多12或2个字节),可以创建一个 空的 给你一个 T* 键入键入您的 map . 但是,考虑到每个 地图 条目需要三个指针加上数据,因此至少是portpin结构本身的两倍大。如果你不小心的话,它会泄漏,当地址被重用时,会引起神秘的错误。(如果您真的不能约束键类,那么这个问题几乎不可能消除。)最后,映射比访问一个字段慢得多,而且更冗长。

        2
  •  1
  •   Tronic    16 年前

    如果您不需要特定的值,您可以简单地将对象的地址转换为(未签名的long)或其他合适的整数类型(ItpTrpTT将是最优的,但它是C99在标准C++中不可用的特性)。

    请注意,上面将对象的每个实例与不同的值相关联。如果您需要类型,如您所说,请使用typeid(t),它为每种类型提供一个唯一的对象(这些对象可以与其他此类对象进行比较)。

        3
  •  1
  •   Brooks Moses    16 年前

    好吧,如果您真正的意思是关联“任何对象”而不是“任何对象值”,那么指针听起来就像它们会做您想要的。但是,它们可能不适用于整数常量之类的东西,因为这些常量的值没有保存在分配的对象中。当然,当某个对象被构造成副本(比如你在函数调用中传递它的值)时,它会创建一个新的对象,所以它会在你的映射中得到一个不同的标记。

    此外,正如potatoswatter的答案中提到的,地址确实会被重用。显然,当对象仍然存在时,它们不能被重用,但是如果不小心,您可能会遇到一些奇怪的情况;对于尚未添加到地图中的对象,您将有错误的条目。所以,在添加映射值之前,不要尝试查找它们,也不要尝试查找已被破坏的对象!

    有了这一点,假设这确实适用于您的用例(并且potatoswatter在对象本身中放置端口和pin值的想法不是更好的想法),那么您不希望将所有指针转换为in t;除了大小问题,这在概念上有点复杂,这就是为什么强制转换是丑陋的。您并不真正关心整数值,只是将指针全部转换为可比较的通用格式——因此,将各种类型的所有T*指针转换为void指针,这是专门为此目的而设计的,并将它们放入 map<void*, PortPin> 地图。

    这也会使一个对象及其第一个组件(以及该组件的第一个组件等等)都具有相同的指针,从而与地图中的相同查找值相关联,这是一个困难。如果需要,可以构造一个同时包含指针和类型标识符(a)的结构 std::type_info 包含 typeid() 对象的,或 int 为其 sizeof() 如果在没有RTTI的情况下编译,那么 Type ID() 不可用),并将其用作地图的标记。