【发布时间】:2021-02-16 20:12:15
【问题描述】:
所以在 Java 中我们有泛型,因此我希望在 C++ 中实现类似于以下的东西
public interface ListenerIF <T> {
public void onChange(T eventData);
}
...
public static void main(String[] args) {
List<ListenerIF<String>> foo = ...;
List<ListenerIF<Integer>> bar = ...;
foo.add((strUpdate) -> {/*some string operation*/});
bar.add((intUpdate) -> {/*some math*/});
foo.forEach((listener) -> listener.onChange("some change"));
bar.forEach((listener) -> listener.onChange(123));
}
但是由于 C++ 模板根本不同(并且需要预先实现所有实现),我试图了解如何使用类型擦除在 C++ 中完成类似的事情(并且由于 JVM 是用 C++ 编写的,我很确定这是可能的,只是躲避我)。
我可以根据ListenerIF 在我想要的地方进行类型擦除,但我不知道如何为函数ListenerIF::onChange(T) 使类型T 动态化。这就是我让 ListenerIF 工作的结果(没有 T 是动态的,这里就像 std::string 一样):
class ListenerIF {
public:
//how do I get the parameter to this function to be dynamic?
virtual void onChange(std::string) = 0;
};
template<typename LISTENER>
class Listener: public ListenerIF {
public:
//how do I get the parameter to this function to be dynamic?
void onChange(std::string update) {
l.onChange(update);
private:
LISTENER l;
};
class Foo {
public:
//how do I get the parameter to this function to be dynamic?
void onChange(std::string);
};
class Bar {
public:
//how do I get the parameter to this function to be dynamic?
void onChange(std::string);
};
void Foo::onChange(std::string update){}
void Bar::onChange(std::string update){}
int main() {
std::vector<ListenerIF *> listeners;
listeners.push_back(new Listener<Foo>());
listeners.push_back(new Listener<Bar>());
for(std::vector<ListenerIF *>::iterator listenersItr = listeners.begin(); listenersItr < listeners.end(); listenersItr++){
(*listenersItr)->onChange("some string update");
}
如果我只想将 'onChange' 用于字符串,这一切都很好,但如果我想将一个完全不同的 'onChange' 类型作为 int、float 或其他一些对象类型,那么这就崩溃了.
我只是不理解一些我遗漏的简单内容吗?
【问题讨论】:
-
旁注:写
listenersItr == listeners.end(),而不是listenersItr < listeners.end()(迭代器==可比较,但不一定++listenersItr,而不是listenersItr++,这个不需要临时的。 -
这更像是伪代码而不是代码。我正在从另一个未接入互联网的工作站转录。
-
您已经在此处发布了正确的关键字作为标签:type-erasure。假设您使用指针(与 java 引用非常相似),您可以使用每个指针类型都可以转换为的类型:
void*,这将允许您执行virtual void onChange(void*) = 0;和void Foo::onChange(void* update){ const std::string* str = dynamic_cast<const std::string*>(update); if (str == nullptr) throw ClassCastException; ... delete str;/* not sure this is the correct place to free the memory */ },但我会考虑质量这段代码相当低......
标签: c++ type-erasure