我有一个C++代码,在这里我比较了来自公共(public)母类Foo
的不同类。如果两个类的类型不同,则比较始终为false
。否则,它将比较特定于该类的一些内部数据。
我的代码如下所示:
class Bar;
class Baz;
class Foo
{
public:
virtual bool isSame( Foo* ) = 0;
virtual bool isSameSpecific( Bar* ){ return false; }
virtual bool isSameSpecific( Baz* ){ return false; }
};
class Bar : public Foo
{
public:
bool isSame( Foo* foo){ return foo->isSameSpecific(this); }
bool isSameSpecific( Bar* bar){ return bar->identifier == identifier; }
int identifier;
};
// and the same for Baz...
这很好用(我认为这是双重调度),我可以仅使用指向
Bar
的指针来比较Baz
和Foo
。但是现在出现了问题。我必须添加一个模板类:
template< typename T>
class Qux : public Foo
{
//...
};
问题是在
Foo
中,我无法为isSameSpecific
声明方法Qux*
,因为它是虚拟的和模板的。问题:是否有任何巧妙的方法可以解决此问题?
最佳答案
这个问题真的没有解决方案:您需要
每个实例化的isSameSpecific
函数
您使用的模板。 (换句话说,在Foo
中:
template <typename T>
virtual bool isSameSpecific( Qux<T>* );
是非法的,但是:
virtual bool isSameSpecific( Qux<int>* );
virtual bool isSameSpecific( Qux<double>* );
// etc.
不是。)
您也许可以摆脱创建摘要的麻烦
QuxBase
,并从中派生Qux<T>
。最有可能的,那只会把问题移到
QuxBase
,但是如果isSameSpecific
不依赖于T
的类型,例如因为您可以定义一些规范的包含类型,所以它可能
可行。不了解
Qux
和isSameSpecific
,很难说。 (如果如果
Qux<T>::isSameSpecific
应该始终返回false
,实例化类型不同,例如,您可以键入
checkin
QuxBase::isSameSpecific
,然后转发到另一个虚拟函数(如果类型相同)。
请注意,类似的问题会影响所有其他替代方式
以及实现多个分派(dispatch)。最后,你是
要求派发一组开放的类型,这意味着
可能无限多的不同功能。
编辑:
请注意:我假设您的
isSame
只是一个例如,实际操作可能会更复杂。
您显示的实际代码显然属于我的建议
第二段;实际上,它甚至可以实现
没有多次 dispatch 。只需定义一个规范的“标识符”
类型,定义一个虚拟的
getCanonicalIdentifier
函数,然后在
isSame
中使用它:bool Foo::isSame( Foo const* other ) const
{
return getCanonicalIdentifier()
== other->getCanonicalIdentifier();
}
就此而言,如果不同类型意味着
isSame
返回false(通常,如果isSame
表示其外观,则返回false一样),您也不需要双重调度:
bool Foo::isSame( Foo const* other ) const
{
return typeid( *this ) == typeid( *other )
&& isSameSpecific( other );
}
派生的
isSameSpecific
将必须转换指针,但是由于可以保证指针是相同的
作为
this
的类型,这是一种简单且安全的操作。最后:如果类没有值语义(并且
如果涉及多态性,几乎可以肯定不应该),
像这样简单:
bool Foo::isSame( Foo const* other ) const
{
return this == other;
}
可能就足够了。
但是,所有这些仅适用于
isSame
之类的东西。如果您还有其他受影响的功能,请返回
达到我最初所说的。
关于c++ - 双重调度和模板类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16186608/