c++是否支持像Java那样的接口的匿名实现?
类似于下面代码中的东西:
Runnable myRunnable =
new Runnable(){
public void run(){
System.out.println("Runnable running");
}
}
###你可以通过创建一个从你定义的接口继承的匿名类的实例来接近它。
例子:
#include <iostream>
struct Runnable {
virtual ~Runnable() = default;
virtual void operator()() = 0;
};
int main() {
struct : Runnable { // anonymous implementation of interface
void operator()() override {
std::cout << "Run Forrest\n";
}
} myRunnable;
myRunnable(); // prints Run Forrest
}
下面是一个将基类指针放在std::vector<std::unique_ptr<Runnable>正如你在这里看到的,匿名实现没什么用。匿名类型就是std::remove_reference_t<decltype(*instance)>。
#include <iostream>
#include <memory>
#include <type_traits>
#include <vector>
// Runnable is defined as in the example above
int main() {
// a collection of Runnables:
std::vector<std::unique_ptr<Runnable>> runners;
{ // create a pointer to an instance of one anonymous impl.
struct : Runnable {
void operator()() override {
std::cout << "Foo\n";
}
} *instance = new std::remove_reference_t<decltype(*instance)>;
runners.emplace_back(instance); // save for later
}
{ // create a pointer to an instance of another anonymous impl.
struct : Runnable {
void operator()() override {
std::cout << "Bar\n";
}
} *instance = new std::remove_reference_t<decltype(*instance)>;
runners.emplace_back(instance); // save for later
}
// loop through all `Runnable`s and ... run them:
for(auto& runner : runners) (*runner)(); // prints "Foo\nBar\n"
}
# # # < blockquote >
c++是否支持类似java的匿名接口实现?
不,不是的。你必须显式定义一个实现类来继承接口并覆盖它的虚方法,例如:
class MyRunnableImpl : public Runnable {
public:
void run() override {
std::cout << "Runnable running";
}
};
Runnable *myRunnable = new MyRunnableImpl;
...
delete myRunnable;
# # #。c++没有这个特性。c++有不同的解决方案来解决Java通过动态实现接口所解决的问题。尽管我们已经接受了这一点,但也许我们仍然可以通过考虑如何在c++中模拟它来学习一些东西
#include <iostream>
#include <type_traits>
struct Runnable {
virtual void run() = 0;
virtual ~Runnable() = default;
};
template <typename F>
auto make_runnable(F f){
struct Runnable_Impl : Runnable {
F f;
Runnable_Impl(F f) : f(f) {}
void run() override {
f();
}
};
return Runnable_Impl{f};
}
void foo(Runnable& r){ r.run(); }
int main(){
auto runnable = make_runnable( [](){ std::cout << "hello world\n";});
runnable.run();
foo(runnable);
auto runn2 = make_runnable( [](){ std::cout << "hello world\n";});
std::cout << std::is_same_v<decltype(runnable),decltype(runn2)>;
}
输出:
hello world
hello world
0
在make_runnable内部,该类型有一个名称,但由于每个lambda表达式的类型不同,使用不同的lambda调用make_runnable将产生不同的类型,这可以通过比较返回对象的类型看出(is_same yield false)。它可以是匿名的,但由于调用者没有看到名称,这并不那么重要。
我还没有见过这种或类似的东西,不过这并不奇怪,因为c++对接口和继承的依赖要比Java少得多。