通过“使用”单独继承的方法覆盖纯虚函数 [英] Overwriting pure virtual functions by 'using' a separately inherited method

查看:112
本文介绍了通过“使用”单独继承的方法覆盖纯虚函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是一个小麻烦真的,因为我可以解决这个问题,通过包装导出的函数,而不是使用'使用关键字,但为什么不下面的工作(编译器告诉我'get_elem'仍然是纯虚拟'Bar'class)。

  class Elem {}; 

class DerivedElem:public Elem {};

class Foo {

public:
virtual Elem& get_elem()= 0;

};

class Goo {

protected:
DerivedElem elem;

public:
DerivedElem& get_elem(){return elem; }

};


class Bar:public Foo,public Goo {

public:
使用Goo :: get_elem;

};

int main(void){

条形栏;

}

干杯,



Tom

解决方案

如果Goo是一个旨在以特定方式实现Foo接口的mixin可以是与其他实现的其他mixins),那么Goo可以从Foo派生(而不是Bar这样做)。



如果Goo不是实现Foo接口,那么将Bar处理为一个可怕的错误,就好像它已经实现了纯虚函数一样,当它实际上恰好具有相同签名的函数时。如果你想隐式接口和鸭键入在C + +你可以做到,但你必须用模板做。正确或错误地,纯虚函数用于显式声明的接口,并且Goo的 get_elem 函数没有显式声明来实现 Foo :: get_elem 。所以它不是。



我想这不解释为什么在原则上,语言不能定义使用Goo :: get_elem for Foo ; 或者Bar中的某些这样的声明,以避免需要Bar包含很多样板包装调用。



使用模板做一些事情,允许 Goo 在某种程度上支持这一点,而不真正了解Foo:

  template< typename T> 
class Goo:public T {

protected:
DerivedElem elem;

public:
DerivedElem& get_elem(){return elem; }
};

class Bar:public Goo< Foo> {};

class Baz:public Goo< Fuu> {};

其中Fuu是一些具有 get_elem 函数。显然, Bar 的作者的责任是确保 Goo 确实实现 Foo ,同样 Baz 检查 Fuu p>

顺便说一下,这种形式的协方差有点诡异。看看Foo,有人可能期望表达式 bar.get_elem()= Elem()是有效的,而不是,因此违反LSP。参考是有趣的。 ((Foo&)bar).get_elem()= Elem()有效,但一般不起作用!它只分配给 Elem 子对象,因此((Foo&)bar).get_elem()= DerivedElem )。多态分配基本上是一个麻烦。


Just a small annoyance really as I can work around the problem by wrapping the derived function instead of using the 'using' keyword but why doesn't the following work (the compiler tells me that 'get_elem' is still pure virtual in 'Bar' class).

class Elem {};

class DerivedElem : public Elem {};

class Foo {

  public:
    virtual Elem&  get_elem() = 0;

};

class Goo {

  protected:
    DerivedElem elem;

  public:
    DerivedElem& get_elem()  { return elem; }

};


class Bar : public Foo, public Goo {

  public:
    using Goo::get_elem;

};

int main(void) {

  Bar bar;

}

Cheers,

Tom

解决方案

If Goo is a "mixin" designed to implement the interface Foo in a particular way (there could be other mixins with other implementations), then Goo can derive from Foo (instead of Bar doing so).

If Goo isn't designed to implement the interface Foo, then it would be a terrible mistake to treat Bar as though it had implemented that pure virtual function, when it fact it just happens to have a function of the same signature. If you want implicit interfaces and "duck" typing in C++ you can do it, but you have to do it with templates. Rightly or wrongly, pure virtual functions are for explicitly declared interfaces, and Goo's get_elem function is not explicitly declared to implement Foo::get_elem. So it doesn't.

I guess that doesn't explain why in principle the language couldn't define using Goo::get_elem for Foo;, or some such declaration in Bar, to avoid the need for Bar to contain a lot of boilerplate wrapping the call.

You can maybe do something with templates to allow Goo to support this to some extent, without really knowing about Foo:

template <typename T>
class Goo : public T {

  protected:
    DerivedElem elem;

  public:
    DerivedElem& get_elem()  { return elem; }
};

class Bar : public Goo<Foo> {};

class Baz : public Goo<Fuu> {};

Where Fuu is some other interface that has a get_elem function. Obviously it's then the responsibility of the author of Bar to ensure that Goo really does implement the contract of Foo, and the same for Baz checking the contract of Fuu.

By the way, this form of covariance is a bit dodgy. Looking at Foo, someone might expect the expression bar.get_elem() = Elem() to be valid, and it isn't, so LSP is violated. References are funny like that. ((Foo &)bar).get_elem() = Elem() is valid but in general doesn't work! It only assigns to the Elem sub-object, and for that matter so does ((Foo &)bar).get_elem() = DerivedElem(). Polymorphic assignment is basically a nuisance.

这篇关于通过“使用”单独继承的方法覆盖纯虚函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆