为什么C不让基类实现派生类的继承接口?

这是我在说什么

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

在一些现有的代码中,人们没有使用模板,但接口类型删除

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与Java不同的地方.

因此,对静态类型为MyBigClass的表达式进行调用,因此对于哪个继承的函数是必需的.

如果只通过基类指针进行写入,那么在派生类中定义写入并不是必需的,这与问题的说法相反.现在,问题改为包含一个纯指示符,在派生类中实现该函数是必要的,以使该类具体和可实例化.

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

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

实际上,这个问题(子对象地址之间的差异)被解决了虚拟继承.但是它需要额外的开销,大部分时间都不是必需的,C指导原则是“你不支付你不使用的费用”.

转载注明原文:为什么C不让基类实现派生类的继承接口? - 代码日志