为什么C ++不让基类实现一个派生类的继承接口? [英] Why does C++ not let baseclasses implement a derived class' inherited interface?

查看:163
本文介绍了为什么C ++不让基类实现一个派生类的继承接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是我在说的

  //某人写了这个,用作模板的政策
struct MyWriter {
void write(std :: vector< char> const& data){
// ...
}
};

在某些现有代码中,人们没有使用模板,但是界面+ type-erasure

  class IWriter {
public:
virtual〜IWriter(){}

public :
virtual void write(std :: vector< char> const& data)= 0;
};

有人想要同时使用这两种方法和写入

  class MyOwnClass:private MyWriter,public IWriter {
// other stuff
};

MyOwnClass是在MyWriter中实现的。为什么MyOwnClass不继承成员函数自动实现IWriter的接口?相反,用户必须编写只调用基类版本的转发函数,如

  class MyOwnClass:private MyWriter, public IWriter {
public:
void write(std :: vector< char> const& data){
MyWriter :: write(data);
}
};

我知道在Java中,当你有一个类实现一个接口,并从一个类有合适的方法,基类自动实现派生类的接口。



为什么C ++不会这样做?

解决方案

这是多重继承,有两个具有相同签名的继承函数, 两者均已实施



在静态类型为 >



如果

/ code>只是通过基类指针调用,然后在派生类中定义 write 是不必要的,与问题中的声明相反。现在问题改为包含一个纯说明符,在派生类中实现该函数是必要的,以使该类具体和可实例化。



MyWriter :: write 不能用于 MyBigClass 的虚拟调用机制,因为虚拟调用机制需要一个接受隐式 IWriter * const this MyWriter :: write 接受隐式 MyWriter * const this 。需要一个新的函数,它必须考虑 IWriter 子对象和 MyWriter 子对象之间的地址差异。 / p>

在理论上,编译器可能会自动创建这个新函数,但是它会很脆弱,因为基类的改变可能突然导致一个新函数选择转发。它在Java中不那么脆弱,只有单一的继承是可能的(只有一个选择是什么函数转发),但是在支持全多重继承的C ++中,选择是不明确的,我们甚至还没有开始钻石继承或虚拟继承。



实际上,这个问题(子对象地址之间的区别)解决了虚拟继承。但是它需要额外的开销,这在大多数时候是不必要的,C ++的指导原则是你不支付你不使用。


Here is what I am talking about

// some guy wrote this, used as a Policy with templates
struct MyWriter {
  void write(std::vector<char> const& data) {
    // ...
  }
};

In some existing code, the people did not use templates, but interfaces+type-erasure

class IWriter {
public:
  virtual ~IWriter() {}

public:
  virtual void write(std::vector<char> const& data) = 0;
};

Someone else wanted to be usable with both approaches and writes

class MyOwnClass: private MyWriter, public IWriter {
  // other stuff
};

MyOwnClass is implemented-in-terms-of MyWriter. Why doesn't MyOwnClass' inherited member functions implement the interface of IWriter automatically? Instead the user has to write forwarding functions that do nothing but call the base class versions, as in

class MyOwnClass: private MyWriter, public IWriter {
public:
  void write(std::vector<char> const& data) {
    MyWriter::write(data);
  }
};

I know that in Java when you have a class that implements an interface and derives from a class that happens to have suitable methods, that base class automatically implements the interface for the derived class.

Why doesn't C++ do that? It seems like a natural thing to have.

解决方案

This is multiple inheritance, and there are two inherited functions with the same signature, both of which have implementation. That's where C++ is different from Java.

Calling write on an expression whose static type is MyBigClass would therefore be ambiguous as to which of the inherited functions was desired.

If write is only called through base class pointers, then defining write in the derived class is NOT necessary, contrary to the claim in the question. Now that the question changed to include a pure specifier, implementing that function in the derived class is necessary to make the class concrete and instantiable.

MyWriter::write cannot be used for the virtual call mechanism of MyBigClass, because the virtual call mechanism requires a function that accepts an implicit IWriter* const this, and MyWriter::write accepts an implicit MyWriter* const this. A new function is required, which must take into account the address difference between the IWriter subobject and the MyWriter subobject.

It would be theoretically possible for the compiler to create this new function automatically, but it would be fragile, since a change in a base class could suddenly cause a new function to be chosen for forwarding. It's less fragile in Java, where only single inheritance is possible (there's only one choice for what function to forward to), but in C++, which supports full multiple inheritance, the choice is ambiguous, and we haven't even started on diamond inheritance or virtual inheritance yet.

Actually, this problem (difference between subobject addresses) is solved for virtual inheritance. But it requires additional overhead that's not necessary most of the time, and a C++ guiding principle is "you don't pay for what you don't use".

这篇关于为什么C ++不让基类实现一个派生类的继承接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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