【问题标题】:Can't inherit two classes that inherit one interface不能继承继承一个接口的两个类
【发布时间】:2021-09-12 18:50:47
【问题描述】:

我有 2 个接口:SocketListeningSocket,以及 2 个类:BerkeleySocketBerkeleyListeningSocket,它们实现了这些接口。 会有更多的socket类型,现在只是一个例子。 问题是BerkeleyListeningSocket 继承了BerkeleySocketListeingSocket。它继承BerkeleySocket 以避免应对基本套接字方法实现,并继承ListeningSocket 来实现侦听套接字方法。 但是类BerkeleySocket和接口ListeningSocket都继承了接口Socket,但是ListeningSocket不像BerkeleySocket那样没有实现它的纯虚方法(在例子中是Close方法),所以我不能创建一个对象BerkeleyListeningSocket 因为错误 unimplemented pure virtual method 'Close'。 说明问题的示例代码:

// This is an example code, so there will be more methods.

// ----------------
// Interfaces
// ----------------

class Socket
{
 public:
  virtual ~Socket() = default;

  virtual void Close() = 0;
};

class ListeningSocket : public Socket
{
 public:
  virtual bool Listen(int max_connections) = 0;
};

// ----------------
// Implementations
// ----------------

// Implementation of base socket.
class BerkeleySocket : public Socket
{
 public:
  explicit BerkeleySocket(SOCKET s) : socket_(s) {}

  ~BerkeleySocket() override { closesocket(this->socket_); }

  void Close() override { closesocket(this->socket_); }

 protected:
  const SOCKET socket_;
};

// Listening socket implementation.
// Inherits BerkeleySocket to avoid coping code of implementation of base socket methods, such as Close.
// There will be more derivatives of BerkeleySocket, so I can't move Close method to BerkeleyListeningSocket.
// Implements ListeningSocket interface. But there is a problem.
// Both BerkeleySocket and ListeningSocket inherits Socket interface,
// so ListeningSocket have unimplemented method Close
// and I can't create an object of BerkeleyListeningSocket because of it.
class BerkeleyListeningSocket : public BerkeleySocket, public ListeningSocket
{
 public:
  explicit BerkeleyListeningSocket(SOCKET s) : BerkeleySocket(s) {}

  bool Listen(int max_connections) override { return listen(this->socket_, max_connections) != SOCKET_ERROR; }
};

int main() {
  // Error! Unimplemented pure virtual method Close.
  BerkeleyListeningSocket listening_socket(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));

  return 0;
}

希望得到您的帮助! 提前致谢!

【问题讨论】:

  • 它继承了 BerkeleySocket 以避免应对基本套接字方法实现 → 这是您设计中的错误。它应该实现接口,但使用实现(作为数据成员)。 — 好吧,错误可能有点大,有充分的理由像你那样做,只是它不一定是你应该做的第一件事。
  • ListeningSocket 不会覆盖Close(),因此Close()BerkeleyListeningSocket 中仍然是纯虚拟的。显而易见的解决方法是在BerkeleyListeningSocket 中覆盖Close(),并在覆盖中调用BerkeleySocket::Close()。或者,也许,使Socket 成为BerkeleySocketListeningSocket 的虚拟基础。从这个问题中不清楚这是否合适。
  • 我不会继承Socket 中的ListeningSocket。事实上,我会将这些接口重命名为:ClosableListener。国际海事组织你把很多东西放在一个班级里。

标签: c++ oop inheritance interface


【解决方案1】:

在这种情况下,您需要 virtual inheritance,因为在您的代码中,BerkeleyListeningSocketSocket 继承了两次(一次从 BerkeleySocket 继承,一次从 ListeningSocket 继承)。为了告诉编译器“将两个Socket 合并为一个”,您需要更改您的类定义:

class ListeningSocket : public virtual Socket
{
// ...
};

class BerkeleySocket : public virtual Socket
{
//
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 2019-08-04
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2015-04-09
    • 1970-01-01
    相关资源
    最近更新 更多