Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
双重分派和模板类 我有一个C++代码,我比较了一个普通的母类派生的不同类, Foo。如果两个类的类型不同,则比较总是false。否则,它会比较特定于类的一些内部数据_C++_Templates_Double Dispatch - Fatal编程技术网

双重分派和模板类 我有一个C++代码,我比较了一个普通的母类派生的不同类, Foo。如果两个类的类型不同,则比较总是false。否则,它会比较特定于类的一些内部数据

双重分派和模板类 我有一个C++代码,我比较了一个普通的母类派生的不同类, Foo。如果两个类的类型不同,则比较总是false。否则,它会比较特定于类的一些内部数据,c++,templates,double-dispatch,C++,Templates,Double Dispatch,我的代码如下所示: 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

我的代码如下所示:

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
{
//...
};
模板
Qux类:公共食品
{
//...
};
问题是,在
Foo
中,我不能为
Qux*
声明方法
isSameSpecific
,因为它是虚拟的和模板的


问题:有什么简单的方法可以解决这个问题吗?

编译器在解析
类Foo
定义时,必须知道
的(有限)组是特定于名称的
虚拟对象。虚拟机在vtable中都有保留条目。模板
Qux
可以被无限次重写,需要在
Foo
中使用无限次的虚拟。显然,即使不尝试描述一种定义它们的方法,这也行不通


您可能可以使用typeinfo来做您想做的事情,但它不会与类型多态性一起使用。

您是对的,这是双重分派,而且您是对的,不幸的是,方法不能同时是
虚拟的
模板的
(后者是一个实现问题)

我担心纯粹的设计不可能做到这一点;但是,你可以在
Qux
中作弊

template <typename T>
class Qux: public Foo {
    virtual bool isSame( Foo* foo ) {
        if (Qux* q = dynamic_cast<Qux*>(foo)) {
            return *this == *q;
        }
        return false;
    }
}; // class Qux
模板
Qux类:公共食品{
虚拟bool-isame(Foo*Foo){
if(Qux*q=动态_-cast(foo)){
返回*this==*q;
}
返回false;
}
}; // 类群
当然,
dynamic\u cast
有点作弊(就像所有针对儿童的演员一样),但是它很管用

注意:
isSame
方法可能应该是
const
并采用
const
参数,也称为
虚拟bool isSame(Foo const*Foo)const

使用RTTI如何:

#include <typeinfo>

struct Foo
{
    virtual ~Foo() { }
    virtual bool compare_with_same(Foo const & rhs) = 0;
};

struct Bar : Foo
{
    int thing;

    virtual bool compare_with_same(Foo const & rhs)
    {
        assert(dynamic_cast<Bar const *>(&rhs) != nullptr);

        return static_cast<Bar const &>(rhs).thing == thing;
    }
}

bool operator==(Foo const & lhs Foo const & rhs)
{
    return typeid(lhs) == typeid(rhs) && lhs.compare_with_same(rhs);
}
#包括
结构Foo
{
虚拟~Foo(){}
虚拟布尔值与相同值比较(Foo const&rhs)=0;
};
结构栏:Foo
{
智力事物;
虚拟布尔值与相同值进行比较(Foo const和rhs)
{
断言(动态_-cast(&rhs)!=nullptr);
返回静态施法(rhs)。thing==thing;
}
}
布尔运算符==(浮点常量和左浮点常量和右浮点常量)
{
返回typeid(lhs)=typeid(rhs)和&lhs。将_与_相同(rhs)进行比较;
}

或者,您可以将
typeid
代码放入每个
compare\u中,并使用相同的
覆盖。这可能会安全一点。

这个问题没有真正的解决方案:您需要 一个
isSameSpecific
函数用于 您使用的模板。(换句话说,在
Foo
中:

template <typename T>
virtual bool isSameSpecific( Qux<T>* );
因此,如果不同类型表示
isame
返回false(通常情况下,如果
isame
表示它的外观,则返回false) 例如),您也不需要双重分派:

bool Foo::isSame( Foo const* other ) const
{
    return typeid( *this ) == typeid( *other )
        && isSameSpecific( other );
}
派生的
isSameSpecific
必须转换 指针,但由于它们保证是相同的 作为此
的类型,这是一种简单而安全的操作

最后:如果类没有值语义(以及 几乎可以肯定的是,如果涉及多态性, 简单到:

bool Foo::isSame( Foo const* other ) const
{
    return this == other;
}
也许就够了

然而,所有这些都只适用于像
isame
这样的东西。 如果您有其他受影响的功能,则返回
对于我最初所说的。

也只制作
Foo
类模板,或者为所有需要的
Qux
编写不同的
isSameSpecific
重载。永远感谢您的评论!模板参数对Foo没有意义,futur类可能有其他模板参数,所以我不想以所有的模板参数结束Foo上可能的模板参数。对于不同的重载,这可能是一个可接受的解决方案,但是T可能有很多种可能性,要编写的重载太多(不是很整洁).看看Andrei Alexandrescu的,特别是图案。@PeterWood很有趣,我来看看!谢谢你的回答!这就是我的想法,这就是每个“虚拟模板”的问题所在方法。Typeinfo是我的默认解决方案,但它不认为它是整洁的。所以,也许解决方案确实改变了我对整洁的定义。谢谢你的答案!你的解决方案可能是我要实现的一个(实际上,我可能在所有相同的方法中做到这一点,并去掉ISAMSimulink)。,除非有更好的主意。是的,演员阵容不符合我的准确定义:-)。对于你的NB:在我的实现中,它实际上是常量,因为它对于理解问题不是必需的,所以我去掉了它。无论如何,谢谢你的建议!一点也不作弊。这里的强制转换对设计不是必需的,只是为了克服语言限制。如果这是一个足够的解决方案,您可以在基类中执行类型检查,并且只有在两种类型相同时才转发到
isSameSpecific
。如果
isSame
总是返回
false
,如果不是,那么在基类中执行检查可能是一个更好的解决方案(即使它涉及RTTI),因为您在基类中强制执行post条件。@JamesKanze:但是会略有不同,因为我提出的解决方案允许将
Qux
K类:公共Qux{}进行比较(无论好坏)。在您的情况下,
isSameSpecific
的签名是什么<代码>Foo*
也是吗?@MatthieuM。签名必须使用
Foo*
,因为要使覆盖生效,签名
bool Foo::isSame( Foo const* other ) const
{
    return typeid( *this ) == typeid( *other )
        && isSameSpecific( other );
}
bool Foo::isSame( Foo const* other ) const
{
    return this == other;
}