c++ - 将模板类的实例添加到向量 (C++)
问题描述
在下面的代码中,我在尝试推fooBaz
送到v
. 这让我感到惊讶,因为Baz
它是Bar
.
为什么这是不允许的,如果想将多个Foo
实例(以从同一基类派生的类为模板)放入向量中,我该怎么办?
#include <iostream>
#include <vector>
template<typename T>
class Foo {};
struct Bar {};
struct Baz : public Bar {};
int main() {
Foo<Bar> fooBar;
Foo<Baz> fooBaz;
std::vector<Foo<Bar>> v;
v.push_back(fooBar);
v.push_back(fooBaz);
return 0;
}
解决方案
Java 泛型与 C++ 模板不同。
类类型的 C++ 值与类类型的 Java 引用变量不同。
您在这里遇到了这两个问题。
C++ 模板为每组模板参数生成一个新的、不相关的类型。你可以创建一个共同的基础,但你必须自己做。
Java 泛型在底层实际上创建了一个类。然后它在输入和输出处写入强制转换操作。
所以一个 Java 泛型,Foo<Base>
并且Foo<Derived>
是相关的,因为 Java 泛型实际上创建了一个Foo<Object>
然后将它包装在强制转换中,并且这些强制转换Foo<Base>
是Foo<Derived>
兼容的。(嗯,并非总是如此Object
,您使用 Java 使用的信息来标记泛型参数,以确定它为其编写 Generic 的实际类型,但这给了您这个想法)。
在 C++ 中,没有关系。(嗯,模板模式匹配给你一个编译时关系,但根本没有运行时关系)
第二个问题是您将类类型的值视为引用。在 C++ 中,aFoo
是一个实际的 foo。它表示一块内存,它是该类的一个实例。在 Java 中,aFoo
是一个智能指针,指向堆上某个遵守Foo
协议的对象(是派生类)。
在 Java 中你不能轻易地创建一个类型的值,你也不能在 C++ 中Foo
轻松地创建一个指向 a 的标记和清除智能指针。Foo
Foo<Bar> fooBar;
Foo<Baz> fooBaz;
这是两种不相关的类型。它们存储在堆栈上(自动存储)。
std::vector<Foo<Bar>> v;
这存储包含Foo<Bar>
打包在一起的对象的内存缓冲区。
v.push_back(fooBar);
这会将fooBar
实例从自动存储复制到vector
.
v.push_back(fooBaz);
这不起作用,因为fooBar
和fooBaz
是不相关的类型。
现在,在c++23反射之前,模仿 Java 在 C++ 中所做的事情是很困难的。您必须手动执行一些步骤。
首先,在手动告知时指示Foo
理解继承:
struct empty_t {};
template<class T, class Base=empty_t>
class Foo:Foo<Base> {};
template<>
class Foo<empty_t, empty_t> {
virtual ~Foo() {}
};
struct Bar {};
struct Baz : public Bar {};
auto fooBar = std::make_unique<Foo<Bar>>();
auto fooBaz = std::make_unique<Foo<Baz, Bar>>();
std::vector<std::unique_ptr<Foo<Bar>>> v;
v.push_back(std::move(fooBar));
v.push_back(std::move(fooBaz));
这编译。
在c++23编译时反射应该让您自动检测基类Baz
并Foo<Baz>
自动继承(Foo<Bases>...
如果需要)。
现在,继承只是在 C++ 中处理多态性的一种方式,但我认为对于今天来说已经足够了。
推荐阅读
- firebase - Firebase + Flutter:安装带有稍后可以与云同步的资产的应用程序
- python - 如何将唯一的班级成员添加到另一个班级
- php - $.getJSON 没有正确返回([object Object],未定义或什么都没有)
- java - 如何在 Spring Boot 中访问 kafka 流上下文之外的 GlobalKTable?
- python - pandas:具有条件公式和唯一值的 groupby
- android - 如何在 Jetpack Compose 中打开表情符号键盘?
- amazon-web-services - 为什么使用多容器端点而不是多模型端点?
- javascript - 未捕获的 DOMException:无法在“窗口”上执行“postMessage”:无法克隆 NodeList 对象
- python - Python循环在循环中保存两次到Excel电子表格选项卡
- c# - 使用 Mailgun 和 Httpclient 发送带有附件的电子邮件