c++中接口的匿名实现

2022-01-29 06:14:38 标签 javac++

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少得多。

阅读全文

▼ 版权说明

相关文章也很精彩
推荐内容
更多标签
相关热门
全站排行
随便看看

错说 cuoshuo.com —— 程序员的报错记录

部分内容根据CC版权协议转载;网站内容仅供参考,生产环境使用务必查阅官方文档

辽ICP备19011660号-5

×

扫码关注公众号:职场神器
发送: 1
获取永久解锁本站全部文章的验证码