如何通过映射实例化派生类中的对象
How to instantiate objects from a derived class via a map
我有一个关于如何通过映射对识别对象的问题,实例化与该对标识的对象,然后将其存储为某种容器(可能是向量)。这里的问题是,我正在寻找的对象都应该是某个基类的派生类。
下面是一个示例:
class BaseClass {
public:
BaseClass() {cout << "BaseClass constructor...n"};
~BaseClass() {cout << "BaseClass destructor...n"};
};
class A : public BaseClass {
public:
A() {cout << "A constructor...n"};
~A() {cout << "A destructor...n"};
};
class B : public BaseClass {
public:
B() {cout << "B constructor...n"};
~B() {cout << "B destructor...n"};
};
class C : public BaseClass {
public:
C() {cout << "C constructor...n"};
~C() {cout << "C destructor...n"};
};
int main(int argc, char *argv[])
{
map <string, BaseClass*> my_map; // Map used to compare a string in order to identify the object type I'd like to make
vector<BaseClass*> keyword_vct; // Vector to store the objects of the different derived class types
BaseClass* ptr;
my_map.insert (make_pair ("A", ptr = new A ));
my_map.insert (make_pair ("B", ptr = new B));
my_map.insert (make_pair ("C", ptr = new C));
string testStr "B";
map <string, BaseClass*> ::const_iterator it = my_map.find(testStr);
if (it == oscards_map.end()) {
cout << "String not found in map." << endl;
}
else {
cout << it->first << "t keyword found in map!" << endl;
BaseClass* pSomekey;
pSomekey = it->second; // This is where I'm lost
keyword_vct.push_back(pSomekey); // Once I instantiate the derived object in the line above, I want to store it in a container.
}
}
所以我的主要问题是:
如何将 pSomekey 转换为类型 A、B 或 C 的对象?
如果我能够实例化其中一个派生类,我是否能够将这些不同类型的对象存储到同一个向量中,因为它们是 BaseClass 的派生类?
我注意到,当我为地图制作对时,它们似乎在各自的派生类中构造了一个对象。
我还注意到,当执行 pSomekey = it->second; 时,不会构造任何对象。
请记住,这是一个示例。 在我的真实代码中,我将比较数百个testStr来制作数百个不同的对象。
任何帮助或建议将不胜感激。谢谢!
- 在基类中添加
virtual
成员函数以创建对象的副本。 - 在派生类中适当地实现它们。
- 需要时调用复制函数。
这是您的代码,在正确的位置更新。
class BaseClass
{
public:
BaseClass() {cout << "BaseClass constructor...n"};
~BaseClass() {cout << "BaseClass destructor...n"};
virtual BaseClass* clone() const = 0;
};
class A : public BaseClass
{
public:
A() {cout << "A constructor...n"};
~A() {cout << "A destructor...n"};
virtual A* clone() const { return new A();}
};
class B : public BaseClass
{
public:
B() {cout << "B constructor...n"};
~B() {cout << "B destructor...n"};
virtual B* clone() const { return new B();}
};
class C : public BaseClass
{
public:
C() {cout << "C constructor...n"};
~C() {cout << "C destructor...n"};
virtual C* clone() const { return new C();}
};
int main(int argc, char *argv[])
{
map <string, BaseClass*> my_map; // Map used to compare a string in order to identify the object type I'd like to make
vector<BaseClass*> keyword_vct; // Vector to store the objects of the different derived class types
BaseClass* ptr;
my_map.insert (make_pair ("A", ptr = new A ));
my_map.insert (make_pair ("B", ptr = new B));
my_map.insert (make_pair ("C", ptr = new C));
string testStr "B";
map <string, BaseClass*> ::const_iterator it = my_map.find(testStr);
if (it == oscards_map.end()) {
cout << "String not found in map." << endl;
} else {
cout << it->first << "t keyword found in map!" << endl;
BaseClass* pSomekey;
pSomekey = it->second;
// Make a copy of the object and store it in keyword_vct.
keyword_vct.push_back(pSomekey->clone());
}
}
将虚拟创建函数添加到基类。
class BaseClass
{
public:
virtual BaseClass* create() const = 0;
};
class A : public BaseClass
{
public:
virtual BaseClass* create() const { return new A; }
};
class B : public BaseClass
{
public:
virtual BaseClass* create() const { return new B; }
};
// ...
keyword_vct.push_back(it->second->create());
pSomekey = it->second;
不创建任何对象的原因是,您只是复制指向对象的指针,而不是对象本身。
>C++不提供内置方式引用"类"并通常创建实例,但是,您可以自己实现它。
正如建议的那样,您可以选择使实例具有虚拟方法来创建类似于 molbdnilo 和 R Sahu 建议的类型化对象。 这称为原型模式
这有一个很好的优势,因为你可以创建各种类型为"A"、"B"和"C"的对象,按照你喜欢的方式设置它们,然后创建它们中的任何一个的副本,只需在你的 std::map 中给它们一个字符串,然后在需要时调用克隆方法。
但是,也有一些缺点。
例如,如果"A"创建或打开了一个文件,那么如果虚拟"A"实际上不打算使用,它应该创建或打开哪个文件? 克隆它会创建另一个试图打开同一文件的"A"?还是创建已创建的文件?
如果"A"、"B"或"C"是相当大的对象,则可以通过使用负责构造更昂贵对象的精简工厂类来节省内存使用量。 这样,内存仅在实际需要时才使用。
如果构造"A"、"B"或"C"需要很长时间,则使用工厂可以节省时间,因为在实际需要之前不需要构造 BaseClass 的实例。
通常,如果派生的 BaseClass 类构造函数包含较大或明显的副作用(CPU、内存、io 等),则使用工厂可以帮助避免这些问题。
下面是如何使用工厂方法模式解决构造问题的示例。
class BaseClass
{
public:
BaseClass() { cout << "BaseClass constructor...n"; };
~BaseClass() { cout << "BaseClass destructor...n"; };
};
class A : public BaseClass
{
public:
A() { cout << "A constructor...n"; };
~A() { cout << "A destructor...n"; };
};
class B : public BaseClass
{
public:
B() { cout << "B constructor...n"; };
~B() { cout << "B destructor...n"; };
};
class C : public BaseClass
{
public:
C() { cout << "C constructor...n"; };
~C() { cout << "C destructor...n"; };
};
class BaseClassFactory
{
public:
virtual ~BaseClassFactory() {}
virtual BaseClass *create() = 0;
};
template <class T>
class BaseClassFactoryImpl : public BaseClassFactory
{
public:
BaseClass *create() override { return new T{}; }
};
int main(int argc, char *argv[])
{
map <string, BaseClassFactory*> my_map; // Map used to compare a string in order to identify the object type I'd like to make
vector<BaseClass*> keyword_vct; // Vector to store the objects of the different derived class types
BaseClass* ptr;
my_map.insert(make_pair("A", new BaseClassFactoryImpl<A>{}));
my_map.insert(make_pair("B", new BaseClassFactoryImpl<B>{}));
my_map.insert(make_pair("C", new BaseClassFactoryImpl<C>{}));
string testStr = "B";
map <string, BaseClassFactory*> ::const_iterator it = my_map.find(testStr);
if (it == my_map.end()) {
cout << "String not found in map." << endl;
}
else {
cout << it->first << "t keyword found in map!" << endl;
BaseClass* pSomekey;
pSomekey = it->second->create(); // Here we ask the factory to create us an instance of whatever BaseClass the factory is setup to return
keyword_vct.push_back(pSomekey); // Once I instantiate the derived object in the line above, I want to store it in a container.
}
}
- 如何使用单独文件中的派生类访问友元函数对象
- 使用基类指针创建对象时,缺少派生类析构函数
- 为什么此派生对象无法访问基类的后递减方法?
- 将带有派生模板的对象传递给接受具有基本模板的对象的功能
- 放置派生C++的新基子对象
- 在 C++ 中将对象转换为派生类型
- 链表包含 c++ 中不同的派生类对象
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 如何在新的派生对象中获取基本对象的数据?
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 获取我的基类以递增派生类对象整数
- 派生类中的对象
- 在没有默认构造函数的情况下创建的派生对象
- OOP 标识派生对象
- 如何创建派生对象的向量?
- 按基类对象访问派生类资源时出错
- 将基类分配给派生对象,反之亦然,以C++以及静态和动态对象之间的差异
- static_cast将此对象派生到C++中的基类
- 如何在构造函数完成后立即销毁从 QWindow 对象派生的内容
- 我可以判断std::type_info对象是否等于另一个对象或从另一个对象派生的类吗?