c++ - c++ - 使用派生类作为抽象类容器的函数中的参数
问题描述
我有以下类层次结构和一个包装类:
struct Base {
virtual ~Base() = default;
virtual void init() = 0;
};
struct DerivedA : Base {
void init() override {
// do something specific to DerivedA
}
};
struct DerivedB : Base {
void init() override {
// do something specific to DerivedB
}
};
struct Wrapper{
Base* _item;
};
现在,我想要一个Wrapper
(eg std::vector<Wrapper>
) 的容器和一个f
期望两个派生类作为参数的函数,如下所示:
void f(DerivedA* d1, DerivedA* d2) {
std::cout << "A vs A" << std::endl;
}
void f(DerivedA* d1, DerivedB* d2) {
std::cout << "A vs B" << std::endl;
}
void f(DerivedB* d1, DerivedB* d2) {
std::cout << "B vs B" << std::endl;
}
void f(DerivedB* d1, DerivedA* d2) {
std::cout << "B vs A" << std::endl;
}
int main() {
std::vector<Wrapper> items;
items.emplace_back(new DerivedA());
items.emplace_back(new DerivedB());
items.emplace_back(new DerivedB());
items.emplace_back(new DerivedA());
for (auto i = 0; i < items.size(); i++) {
for (auto j = i+1; j < items.size(); j++) {
// do something wizh all item pairs
f(items[i]._item, items[j]._item);
}
}
return 0;
}
这不会编译,因为编译器确实期望声明f(Base* b1, Base* b2)
,这当然是有道理的。
到目前为止我尝试了什么:
- 用于
enum class DerivedType { A, B, C };
破译派生类的类型。这有效,但看起来很笨拙。 - 使用模板版本
Wrapper
并将每种模板类型存储在不同的容器中,例如std::vector<Wrapper<DerivedX>>
. 再次,这感觉就像我做错了什么。 std::variant<DerivedA, DerivedB> _item
代替Base* _item
in使用Wrapper
。但是我无法std::visit
以我需要的方式返回指向派生类的指针f
(因为operator()(DerivedX* d)
对于 any 期望相同的返回X
)。
有哪些可能的方法来实现这一点?我正在寻找的解决方案是否存在?
解决方案
使用基于 RTTI 的解决方案也是一种选择:
void f1(Base* d1, Base* d2) {
const auto& t1 = typeid(*d1);
const auto& t2 = typeid(*d2);
if (t1 == typeid (DerivedA) && t2 == typeid (DerivedA)) {
std::cout << "A vs A" << std::endl;
}
if (t1 == typeid (DerivedA) && t2 == typeid (DerivedB)) {
std::cout << "A vs B" << std::endl;
}
if (t1 == typeid (DerivedB) && t2 == typeid (DerivedA)) {
std::cout << "B vs A" << std::endl;
}
if (t1 == typeid (DerivedB) && t2 == typeid (DerivedB)) {
std::cout << "B vs B" << std::endl;
}
}
推荐阅读
- typescript - 如何使用角度生命周期钩子在扩展面板中显示第三级或更多级嵌套面板的内容
- c# - C# - 下载时进度条保持在 0% (webclient)
- html - 使用 flexbox 保持容器居中并在调整大小时缩小
- laravel - Laravel Spark 中的图标
- yaml - 基于 _data 文件的条件 Jekyll Liquid 类
- ios - 泛型 Objective-C 类的扩展无法在运行时访问该类的泛型参数
- featherlight.js - 关闭后无法重新打开featherlight div
- java - java.io.IOException:尝试读取 aws s3 存储桶上的已关闭流
- javascript - 无法解析 'lodash/fp - 谷歌地图
- java - Guice 中的子注射器会自动创建吗?