0

对于我的问题的技术部分,我得到了一个很好的答案,即为什么我目前的处理方法不起作用(分配derived**base**是类型不安全的,另请参阅将 Derived** 转换为 Base** 和 Derived* 到 Base*)。但是,我仍然不知道如何以 C++ 方式实现我的想法。我开始一个新问题,因为最后一个标题太具体了。

这可能是对我正在尝试做的事情的更清晰的解释:

  1. 创建多个对象,这些对象都是从一个类派生的类的实例。
  2. 将这些对象与编译时人类可读的标识符(可能是字符串?)一起存储在某种类型的主容器中。
  3. 从其他组件获取标识符列表,搜索主容器,并将它们传回(指针/引用)相应的对象,以便它们可以读取/修改它们。我认为此时我需要打破类型安全,并假设组件知道它们通过标识符请求的派生类型。

我认为这对于映射、向量和指向对象的指针来说会相对简单和优雅(我在上一个问题中给出了一个简化的示例),但似乎我将不得不做很多 C-样式类型转换以允许组件传递指向位置的指针以存储来自主容器的值。这向我表明我没有遵循 C++ 范式,但我“应该”做什么?

[编辑]这是我如何设想的一些假设示例代码,希望这能澄清我的想法:

#include <map>
#include <vector>
#include <string>
using namespace std;

class BaseObj {};
class Der1Obj: public BaseObj {};
class Der2Obj: public BaseObj {};

typedef map<string, BaseObj**> ObjPtrDict;
typedef map<string, BaseObj*> ObjDict;

class BaseComp
{
public:
   ObjPtrDict objs;
};

class DervComp
{
   DervComp(){objs["d1"] = &d1; objs["d2"] = &d2; } // This wouldn't compile
   Der1Obj* d1;
   Der2Obj* d2;
}

typedef vector<BaseComp*> CompList;

void assign_objs(CompList comps, ObjDict objs)
{
   for (auto c = comps.begin(); c != comps.end(); c++)
     for (auto o = c.objs.begin(); o != c.objs.end(); o++)
       *(o->second) = objs[o->first];
}

int main(int argc, char* argv[])
{
    Der1Obj d, d1;
    Der2Obj d2;
    ObjDict objs;
    objs["d"] = &d;
    objs["d1"] = &d1;
    objs["d2"] = &d2;

    DervComp c;
    vector<DervComp*> comps;
    comps.push_back(&c);

    assign_objs(comps, objs); 

    return 0;
}
4

3 回答 3

0

我读了你的另一篇文章,但我想我不明白你为什么要使用双指针。据我了解,您只需使用普通指针即可。

例如

class Base
{
};

class Deriv : public Base
{
};

std::map< std::string, Base* > ObjectStore;

function Component1( ... )
{
   Base* b = ObjectStore[ "MyObject" ];
   b->DoSomeFancyStuff();
}

function ModifyObjectStore( )
{
   delete ObjectStore[ "MyObject" ];
   ObjectStore[ "MyObject" ] = new Derived(); 

}

我希望这有帮助。

于 2012-07-12T12:12:15.007 回答
0

如果我得到了你想要的,你可以这样做:

#include <vector>

class Base
{
public:
    enum eDerived
    {
    //name these whatever you like
        DER1,//for first derived class
        DER2,//for second derived class
        DER3//for third derived class
    };

    virtual eDerived type() = 0;//this will return the class type.
};

class Derived1: public Base
{
public:
    virtual eDerived type() { return DER1; }
};

class Derived2: public Base
{
public:
    virtual eDerived type() { return DER2; }
};

class Derived3: public Base
{
public:
    virtual eDerived type() { return DER3; }
};

int main()
{
    std::vector<Base*> myList;//container for all elements
    //You can store a pointer to any of the derived classes here like this:
    Base * a = new Derived1();
    Base * b = new Derived2();
    Base * c = new Derived3();

    myList.push_back(a);
    myList.push_back(b);
    myList.push_back(c);

    //Iterating through the container
    for( Base * tmp: myList)
    {
        //You can check the type of the item like this:
        if( tmp->type() == Base::DER1 )
        {  
            //and cast to a corresponding type.
            //In this case you are sure that you are casting to the right type, since
            //you've already checked it.
            Derived1 * pointerToDerived1 = static_cast<Derived1 *>(tmp);
        }
    }
}

Ofc 你可以选择任何类型的容器。如果你想给他们一个 ID,你可以使用map,或者将它添加到类本身中。

于 2012-07-12T12:03:49.930 回答
0

您说,“将它们传回相应的对象”。为此,您为什么要回传基地**?您可以简单地将 a 映射从字符串返回到指针。请参阅下面的代码进行解释。

class Container
{
    void add(const string& aKey_in, Base* b)
    {
        myObjects[aKey_in] = b;
    }
    void getObjs(list<string> aKeys_in, map<string,Base*>& anObjMap_out)
    {
        for(all string s in the aKeys_in)
            anObjMap_out[s] = myObjects[s];
    }
private:
    map<string, base*> myObjects;
};

您的条件在这里满足: 创建许多对象,这些对象都是从一个类派生的类的所有实例。 您可以扩展该类以具有创建逻辑、工厂逻辑等。

将这些对象与编译时人类可读的标识符(可能是字符串?)一起存储在某种类型的主容器中。 用地图实现

从其他组件获取标识符列表,搜索主容器,并将它们传回(指针/引用)相应的对象,以便它们可以读取/修改它们。我认为此时我需要打破类型安全,并假设组件知道它们通过标识符请求的派生类型。

您不需要将指针传回指向客户端的指针。只需传回对象指针。

附加说明:您可以使用 shared_ptr 而不是原始指针来实现指针。如果您的客户端代码(使用 getObjs() 方法的任何人)编写正确,那么您将不需要从基指针到派生指针的动态转换。他们应该能够使用基指针。无论如何,这是一个你还没有问过的不同的问题。

于 2012-07-12T12:21:54.460 回答