我已经开发了以下代码来尝试实现非虚拟多态性:
#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
任何关于此模式作为虚拟继承和设计的替代品的想法都值得赞赏。
如果我能澄清任何事情,请告诉我。
编辑: 我问这个问题是为了尝试确定是否有任何理由可以证明这样的设计是实现非虚拟多态性的合适方法,如果不是,那是为什么?
最佳答案
您的代码是一种有趣的方法。这是一个很好的概念证明,但它有一个主要缺陷:它不能一致地管理继承!
问题:类继承
假设我想创建一个类 testcase22
继承自 testcase2
, 但有自己的实现 bar()
.
备选方案 1:如果我通过继承 testcase2
来天真地定义它, 它将使用 bar_implementation
的 testcase2
:
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 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 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;
}
};
这可以通过定义从 base 虚拟继承的 foo 来解决:
class foo:public virtual base { ... };
然后它会编译,但它仍然会使用 bar_implementation
的 testcase2
而不是来自 testcase22
的那个.顺便说一句,即使它会起作用,虚拟基也会阻止在您的类族中使用多重继承的可能性。
结论
您的构造很好,但只有一个简单继承级别。
这是一个主要的限制。尤其是当考虑到多态性的好处是管理自然层次结构以最好地利用继承关系时。
与易于使用的虚函数相比,您的模式使用起来也相对复杂。如果使用多个多态函数(其中一些甚至重载),您的代码会是什么样子?
您打算通过您的模式实现的目标尚不清楚,但老实说,对于必须维护数年的现实生活项目,我不会采用这种方法。但这当然是我自己的主观意见。
关于c++ - C++ 中的非虚拟多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28079685/