Reputation: 412
Does C++ support anonymous implementation of interface like Java?
Something similar like in following code:
Runnable myRunnable =
new Runnable(){
public void run(){
System.out.println("Runnable running");
}
}
Upvotes: 3
Views: 468
Reputation: 117298
You can get pretty close by creating an instance of an anonymous class that inherits from your defined interface.
Example:
#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
}
Here's a contrived example, putting base class pointers to instances of different anonymous implementations of Runnable
in a std::vector<std::unique_ptr<Runnable>>
. As you can see here, making the implementations anonymous serves little purpose. The anonymous type is simply 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"
}
Upvotes: 7
Reputation: 122228
No. C++ does not have this feature. C++ has different solutions for the problems that Java solves with such on-the-fly implementations of interfaces. Though, having accepted that, maybe we can still learn something by considering how it could be emulated in 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
Inside make_runnable
the type has a name, but because each lambda expression is of different type, a call to make_runnable
with a different lambda will yield a different type as you can see by comparing the types of the returned objects (is_same
yields false
). It could be anonymous, but as the caller doesn't get to see the name, that doesn't matter that much.
I haven't seen this or similar in the wild, though thats not a big surprise because C++ relies much less on interfaces and inheritance than Java.
Upvotes: 1
Reputation: 595827
Does c++ support anonymous implementation of interface like java?
No, it does not. You must explicitly define an implementation class to inherit from the interface and override its virtual methods, eg:
class MyRunnableImpl : public Runnable {
public:
void run() override {
std::cout << "Runnable running";
}
};
Runnable *myRunnable = new MyRunnableImpl;
...
delete myRunnable;
Upvotes: 2