【发布时间】:2021-07-29 06:33:04
【问题描述】:
我有一个包装类,它通过一个公共基类的引用向量来保存一堆派生类对象。在运行时,子对象是根据用户输入创建的。
#include <iostream>
#include <vector>
#include <memory>
#include <type_traits>
class Base {
public:
virtual void run() = 0;
};
class Wrapper {
public:
std::vector<std::shared_ptr<Base>> blocks;
template <class Child>
auto create() -> std::shared_ptr<Child>
{
auto block = std::make_shared < Child > ();
blocks.emplace_back(block);
return std::move(block);
}
template <typename A, typename B>
void connect(A a, B b)
{
using connectionType = typename A::element_type::out;
connectionType* port = new connectionType;
a.get()->ptr_out = port;
b.get()->ptr_in = port;
}
};
class Child_1 : public Base {
public:
using in = int;
using out = float;
out* ptr_out;
in* ptr_in;
void run() { std::cout<<"running child 1\n"; *ptr_out = 1.234;};
};
class Child_2 : public Base {
public:
using in = float;
using out = bool;
out* ptr_out;
in* ptr_in;
void run() { std::cout<<"running child 2\ngot: "<<*ptr_in; };
};
int main () {
Wrapper wrapper;
/* read config file with a list of strings of which types to create */
std::vector < std::string > userInput;
userInput.push_back("Type 0");
userInput.push_back("Type 1");
for (auto input:userInput)
{
if (input == "Type 0")
wrapper.create < Child_1 > ();
else if (input == "Type 1")
wrapper.create < Child_2 > ();
/* and so on */
}
/* read config file with a list of pairs of which objects to connect */
std::vector < std::pair < int, int >>connections;
connections.push_back(std::make_pair(0, 1));
// e.g. user wants to connect object 0 with object 1:
for (int i = 0; i < connections.size (); i++)
{
auto id0 = connections[i].first; // e.g. 0
auto id1 = connections[i].second; //e.g. 1
// this will not work because Base has no typename in / out:
// wrapper.connect (wrapper.blocks[id0], wrapper.blocks[id1]);
// workaround:
wrapper.connect(
std::dynamic_pointer_cast<Child_1>(wrapper.blocks[id0]),
std::dynamic_pointer_cast<Child_2>(wrapper.blocks[id1]));
}
wrapper.blocks[0].get()->run();
wrapper.blocks[1].get()->run();
return 0;
}
现在,我只能存储 Base 对象的向量,这些对象不能保存每个派生对象的不同输入/输出类型。 当我想连接派生对象(存储为基类对象)时,我需要将它们动态指针转换回它们的派生类。最有效的方法是什么?
我能想到几种方法 - 用 C++ 似乎都不可能(据我所知):
- 有某种查找表/枚举,它返回要转换到的类型;然后我可以从用户输入“Type 0”等创建一个映射到该类型并进行相应的转换。
- 有某种类似 lambda 的表达式,可以返回正确转换的指针类型,以便我可以调用
wrapper.connect( lambda_expression(...), lambda_expression(...) )。 - 蛮力:检查每个可能的用户输入组合,并使用 dynamic_pointer_cast 调用连接函数(如编码示例所示)。这很可能不适合我的实际应用程序(目前使用大约 25 个这样的类),因为它会导致大量不可维护的函数调用......
- 不知何故将通用输入/输出类型提供给基类,但我想不出任何方法。
我真的希望我遗漏了一些明显的东西。非常感谢任何帮助。
【问题讨论】:
-
我自己不喜欢
dynamic_cast。它不能很好地扩展。我的偏好是根据需要在基类中声明纯虚方法,然后在子类中覆盖它们以适应。 -
在这种情况下我将如何使用纯虚函数?我需要根据派生类类型定义从包装器调用模板化连接函数。我需要某种类型由派生类定义的虚拟成员变量。
-
return std::move (block);可以简单地为return block;。
标签: c++ types derived-class base-class