我对my question的技术部分得到了一个很好的答案,说明为什么我当前的方法不起作用(将derived**
指定给base**
类型不安全,另请参阅{ {3}})。但是,我仍然不知道如何以C ++方式实现我的想法。我正在开始一个新问题,因为最后一个标题太具体了。
这可能是我想要做的更明确的解释:
我认为这对于地图,向量和指向对象的指针来说相对简单和优雅(我在Converting Derived** to Base** and Derived* to Base*中给出了一个简化示例),但似乎我必须做许多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;
}
答案 0 :(得分: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
,也可以将其添加到班级中。
答案 1 :(得分:0)
我读了你的另一篇文章,但我想我不明白为什么你会使用双指针。根据我的理解,你只需使用普通指针。
E.g。
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();
}
我希望这会有所帮助。
答案 2 :(得分:0)
你说,“将它们传回相应的对象”。为此你为什么要传回基地**?您可以简单地将字符串从字符串返回到指针。请参阅以下代码以获取解释。
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()方法的人)被正确编写,那么您将不需要从基指针到派生指针的动态转换。他们应该能够使用基指针。 无论如何,这是一个你尚未提出的另一个问题。