bis*_*ash 22 c++ inheritance templates pointers interface
我有如下代码.我有一个抽象模板类Foo和两个子类(Foo1和Foo2),它们派生自模板的实例化.我希望在我的程序中使用指向Foo1或Foo2类型的对象的指针,因此我创建了一个接口IFoo.
我的问题是我不确定如何在界面中包含functionB,因为它依赖于模板实例化.甚至可以通过界面使functionB可访问,还是我尝试不可能?
非常感谢您的帮助.
class IFoo {
public:
virtual functionA()=0;
};
template<class T>
class Foo : public IFoo{
public:
functionA(){ do something; };
functionB(T arg){ do something; };
};
class Foo1 : public Foo<int>{
...
};
class Foo2 : public Foo<double>{
...
};
Run Code Online (Sandbox Code Playgroud)
Mat*_* M. 17
你实际上在尝试不可能的事.
事情的非常心脏很简单:virtual和template不拌匀.
template是关于编译时代码生成.您可以将其视为某种类型感知宏+一些用于元编程的技巧.virtual 是关于运行时决定,这需要一些工作.virtual通常使用虚拟表来实现(想象一下列出方法的表).需要在编译时知道方法的数量,并在基类中定义.
但是,根据您的要求,我们需要一个无限大小的虚拟表,其中包含我们尚未看到的类型的方法,并且只会在未来几年内定义......遗憾的是不可能.
如果可能的话?
嗯,这没有意义.当我打电话,会发生什么Foo2用int?它并不意味着它!因此它打破了Foo2实现所有方法的原则IFoo.
所以,如果你说出真正的问题会更好,这样我们可以在设计层面而不是技术层面帮助你:)
最简单的方法是使您的界面模板化.
template <class T>
class IFoo {
public:
virtual void functionA()=0;
virtual void functionB(T arg){ do something; };
};
template<class T>
class Foo : public IFoo<T>{
public:
void functionA(){ do something; };
void functionB(T arg){ do something; };
};
Run Code Online (Sandbox Code Playgroud)
由于 functionB 的参数类型必须提前知道,因此您只有一个选择:使其成为可以容纳所有可能的参数的类型。这有时被称为“顶级类型”,并且 boost 库的类型any非常接近顶级类型的功能。这是可行的:
#include <boost/any.hpp>
#include <iostream>
using namespace boost;
class IFoo {
public:
virtual void functionA()=0;
virtual void functionB(any arg)=0; //<-can hold almost everything
};
template<class T>
class Foo : public IFoo{
public:
void functionA(){ };
void real_functionB(T arg)
{
std::cout << arg << std::endl;
};
// call the real functionB with the actual value in arg
// if there is no T in arg, an exception is thrown!
virtual void functionB(any arg)
{
real_functionB(any_cast<T>(arg));
}
};
int main()
{
Foo<int> f_int;
IFoo &if_int=f_int;
if_int.functionB(10);
Foo<double> f_double;
IFoo &if_double=f_double;
if_int.functionB(10.0);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,any_cast不知道通常的转换。例如any_cast<double>(any(123))抛出异常,因为它甚至没有尝试将整数 123 转换为双精度。如果不关心转换,因为无论如何都不可能复制所有转换。因此存在一些限制,但如有必要,可以找到解决方法。
我不认为你能得到你想要的。如果您要实现您的建议,请考虑一下:如果您有一个指向IFoo实例的指针并且您调用functionB(),您应该给它什么类型的参数?根本问题是Foo1::functionB和Foo2::functionB具有不同的签名并执行不同的操作。
| 归档时间: |
|
| 查看次数: |
30698 次 |
| 最近记录: |