如何解决函数参数的 C++ 类型擦除
所以在 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
方面获得我想要的类型擦除,但我不知道如何使 T
函数的类型为动态 ListenerIF::onChange(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 或其他一些对象类型,那么这会崩溃.
我是否只是不理解我遗漏的一些简单内容?
解决方法
Java 版本 (ListenerIF<T>
) 中未擦除参数。
等效的 C++ 也会保留参数:
template <typename T> // <- need a template parameter
class listener_interface {
public:
virtual void on_change(const T& data) = 0;
};
,
您需要将模板应用到 ListenerIF
本身,就像 Java 代码一样,例如:
#include <vector>
#include <memory>
template <typename T>
class ListenerIF {
public:
virtual ~ListenerIF() {};
virtual void onChange(const T &eventData) = 0;
};
template <typename T>
using listenerIF_ptr = std::unique_ptr<ListenerIF<T>>;
...
class FooListener : public ListenerIF<std::string> {
public:
void onChange(const std::string &eventData) override {
/* some string operation */
}
};
class BarListener : public ListenerIF<int> {
public:
void onChange(const int &eventData) override {
/* some math */
}
};
...
int main() {
std::vector<ListenerIF_ptr<std::string>> foo;
std::vector<ListenerIF_ptr<int>> bar;
foo.push_back(std::make_unique<FooListener>());
bar.push_back(std::make_unique<BarListener>());
for(auto &listener : foo) { listener->onChange("some change"); }
for(auto &listener : bar) { listener->onChange(123); }
}
但是,在这种情况下,我建议将 std::function
(甚至是普通函数指针)与 lambdas 一起使用,而不是使用多态接口类型,例如:
#include <vector>
#include <functional>
template <typename T>
using listenerIF = std::function<void(const T&)>;
// or: listenerIF = void(*)(const T&);
int main() {
std::vector<listenerIF<std::string>> foo;
std::vector<listenerIF<int>> bar;
foo.push_back(
[](const std::string &eventData){
/* some string operation */
}
);
bar.push_back(
[](const int &eventData) {
/* some math */
}
);
for(auto &listener : foo) { listener("some change"); }
for(auto &listener : bar) { listener(123); }
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。