老实说,我不喜欢虚拟调度Interface类。因此,我想实现自己的类而没有任何基本抽象类。为了形象起见,我正在实现MyCustomWidget,并且已经实现了其中的一些方法,而没有实现,因为没有必要。

// here is my custom widget class, which 'show' method is implemented, but 'close' method is not.
struct MyCustomWidget
{
    void show(){ std::cout << "Hey" << std::endl; }
    //void close(){ std::cout << "Bye"  << std::endl; }
};

// here is your custom widget class, which 'show' is not implemented but 'close' is .
struct YourCustomWidget
{
    //void show(){}
    void close(){ std::cout << "Bye" << std::endl;}
};

// common widget class, which may stored within any custom widgets.
struct Widget
{
    Widget() = default;

    template< typename CustomWidget >
    void add(CustomWidget cw)
    {
        auto child = std::make_unique< proxy<CustomWidget> >( std::move( cw ) )
        childs.push_back( std::move(child ) );
    }
    void show()
    {
        for(auto & e : childs)
            e->show();
    }
    void close()
    {
        for(auto& e : childs)
            e->close();
    }
private:
    struct proxy_base
    {
        virtual void show() = 0;
        virtual void close() = 0;
        virtual ~proxy_base(){}
    };

    template< typename CustomWidget >
    struct proxy : public proxy_base
    {
        explicit proxy(CustomWidget cw_) : cw( std::move(cw_ ) )
        {}

        void show() override final
        {    // -------------->>>>>> (1)
            // call cw.show()  if cw has 'show' method, otherwise nothing.
        }
        void close() override final
        {     /// ---------------->>>> (2)
            // call cw.close if cw has a 'close' method, otherwise nothing.
        }

        CustomWidget cw;
    };

std::vector< std::unique_ptr< proxy_base > >childs;
};

int main()
{
     Widget w;
     w.add( MyCustomWidget() );
     w.add( YourCustomWidget() );

     w.show();
     //.... a lot of code

     w.close();
}


我的问题很简单:我如何实现(1)和(2)虚方法?

编辑:我看到这个问题已经得到解答。让我改变我的问题。
问题2:(1)和(2)方法是“最终的”,并且在基类中将它们声明为纯虚拟方法,对于这种情况,编译器可以优化虚拟表,并避免使用它?
我对GCC,CLang和Visual Studio 2013感兴趣。

最佳答案

您可以将它们放在代理类的private部分中:

template<typename T>
auto show_helper(int) -> decltype( std::declval<T>().show(), void())
{
    cw.show();
}

template<typename T>
void show_helper(...) { }


然后从show这样称呼他们:

show_helper<CustomWidget>(0);


仅当尾随返回类型的表达式格式正确,即T具有show方法时,才会实例化第一个重载。

这称为表达式SFINAE,比pmr的答案比C ++ 11之前的版本短得多。它还使您更轻松地指定show的签名,因此更加灵活。另一个答案只能给您带来积极的结果,只是发现您无法在没有参数的情况下调用show。选择你的毒药。

Live example.

关于c++ - 在c++ 11中实现条件虚拟方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21861743/

10-14 23:56
查看更多