我有一个 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...
这很好用(我认为这是双重 dispatch ),我可以比较 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
如果
实例化类型不同,例如,您可以键入
打卡QuxBase::isSameSpecific
, 并转发给另一个
如果类型相同则为虚函数。)
请注意,类似的问题会影响所有替代方法 也实现多重分派(dispatch)。最后,你是 要求通过一组开放的类型进行调度,这意味着 可能有无限数量的不同功能。
编辑:
需要说明的是:我假设您的 isSame
只是一个
例如,实际操作可能更复杂。
您显示的实际代码显然符合我的建议
第二段;事实上,它甚至可以实现
没有多次 dispatch 。只需定义一个规范的“标识符”
类型,定义一个虚拟 getCanonicalIdentifier
功能,和
在 isSame
中使用它:
bool Foo::isSame( Foo const* other ) const
{
return getCanonicalIdentifier()
== other->getCanonicalIdentifier();
}
就此而言,如果不同的类型意味着 isSame
返回 false(通常是这种情况,如果 isSame
表示它看起来的样子
像),你也不需要双重调度:
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++ - 双重分派(dispatch)和模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16186608/