C++ 中的非虚拟多态性

Non-Virtual Polymorphism in C++

我开发了以下代码以尝试实现非虚拟多态性:

#include <functional>
#include <iostream>
namespace{
    using std::function;
    class base {
    protected:
        using signiture =void(void);
        using func_t = function<signiture>;
        ~base(){}
    public:
        func_t bar;//std::function object to a function of type "signature"
    };
}
template <typename implementation>
class foo:public base {
public:
    foo(implementation* instance){
        bar = func_t(std::bind(&implementation::bar_implementation,instance));
//binds a function of name "bar_implementation" from class implementation to the std::function object
//binds to object "instance"
    }
};
typedef base foo_base;

class testcase:public foo<testcase> {
public:
    friend class foo;//allows implementations to be protected or private
    testcase():foo(this){}//sends instance to the constructor of the base class in order to enable binding
protected:
    void bar_implementation(void){
        std::cout<<"Hello"<<std::endl;
    }
};
class testcase2:public foo<testcase2> {
public:
    friend class foo;//allows implementations to be protected or private
    testcase2():foo(this){}
protected:
    void bar_implementation(void){
        std::cout<<"World!"<<std::endl;
    }
};


int main(int argc, const char * argv[]) {
    testcase t;
    testcase2 t2;

    foo_base* b = &t;
    foo_base* b2 = &t2;
    b->bar();
    b2->bar();
    return 0;
}

实际上这段代码分布在几个文件中...

我想知道我的代码中是否有任何内容可以被视为不良做法、未定义的行为或在某些庄园中不受欢迎的其他行为? A Live Example

任何关于此模式作为虚拟继承和设计的替代品的想法都值得赞赏。

如果我能澄清任何事情,请告诉我。

编辑: 我问这个问题是为了尝试确定是否有任何理由可以说明为什么像这样的设计是实现非虚拟多态性的合适方法,如果不是,那是为什么?

您的代码是一种有趣的方法。这是一个很好的概念证明,但它有一个主要缺陷:它不能一致地管理继承 !

问题:class继承

Suppose 我想创建一个继承自 testcase2 的 class testcase22,但有自己的 bar() 实现。

备选方案1:如果我通过继承testcase2来天真地定义它,它将使用testcase2bar_implementation

    class testcase22:public testcase2  {
    public:
        testcase22() {}   // naive contructor
    protected:
        void bar_implementation(void){    // will not be used
            std::cout<<"Great!"<<std::endl;
        }
    };

备选方案 2:如果我尝试使用您的构造函数模式,由于编译错误,它不会工作。因为类型推导将使用 foo<testcase2>,它不是 testcase22 的直接基础 class,因此不能在 mem-initializer 列表中使用:

    class testcase22:public testcase2  {
    public:
        friend class foo;//allows implementations to be protected or private
        testcase22():foo(this){}   // !!!!! causes compile error
    protected:
        void bar_implementation(void){
            std::cout<<"Great!"<<std::endl;
        }
    };

备选方案 3:如果我显式使用 foo,它将不起作用,因为 foo os 不是有效的基类型初始值设定项。

备选方案 4:如果我尝试使用多重继承,我会遇到模棱两可的基础 class

    class testcase22:public testcase2, public foo<testcase22> {
    public:
        friend class foo;//allows implementations to be protected or private
        testcase22():foo(this){}
    protected:
        void bar_implementation(void){
            std::cout<<"Great!"<<std::endl;
        }
    };

这可以通过定义 foo 从 base 虚拟继承来解决:

    class foo:public virtual base { ... };

然后它会编译,但它仍然会使用 testcase2bar_implementation 而不是 testcase22bar_implementation。顺便说一句,即使可行,虚拟基础也会阻止 pos 对 class 家族使用多重继承的可能性。

结论

您的构造很好,但仅适用于单层简单继承。

这是一个主要限制。尤其是当考虑到多态性的好处是管理自然层次结构以最好地利用继承关系时。

与易于使用的虚函数相比,您的模式使用起来也相对复杂。如果使用多个多态函数(其中一些甚至重载),您的代码会是什么样子?

您打算通过您的模式实现的目标尚不清楚,但老实说,对于必须维护数年的现实生活项目,我不会采用这种方法。但这当然是我自己的主观意见。