我相信这是一个反复出现的模板模式的例子。在我看来,这应该编译,但不是。这是Xcode 8.3中的Clang。

template<class T>
class Fungeable
{
public:
    virtual ~Fungeable() {}
    virtual bool funge( const Fungeable<T>& inFungeable ) const = 0;
};

class Blarg : public Fungeable<Blarg>
{
public:
    virtual bool funge( const Blarg& inFungeable ) const override { return true; }
};

int main(int argc, const char * argv[]) {
    Blarg b;
    Blarg x;
    return static_cast<int>( b.funge( x ) );
}

看来这应该可行,因为Blarg是Fungeable。但是我收到错误'funge' marked 'override' but does not override any member functions
如果我将Blarg::funge()的签名更改为采用这样的Fungeable<Blarg>:
class Blarg : public Fungeable<Blarg>
{
public:
    virtual bool funge( const Fungeable<Blarg>& inFungeable ) const override { return true; }
};

然后编译。

因为Blarg在定义上是Fungeable<Blarg>,所以第一个版本不应该工作吗?

最佳答案

协变量参数类型没有,从没有,而且很可能永远不会在C++中起作用。您可能会认为您的示例“显然”是安全的。但是该功能通常是不安全的,并且不会为如此小的用例添加支持。

为了显示:

struct food {};
struct grass : food {};

struct animal {
  virtual void eat(food&) = 0;
};

void feed(animal& a) {
  a.eat(grass{});
}

到现在为止还挺好。现在,假设我们有协变参数类型,让我们向层次结构添加更多:
struct meat : food {};

struct lion : animal {
  void eat(meat&) {/*...*}
};

当我将lion对象传递给feed时会发生什么?它不能将grass当作食物来处理,但是是- animal。这违反了Liskov替代原则。

关于c++ - 为什么这个奇怪的循环模板模式示例无法编译?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46030687/

10-09 06:38