我正在使用一个实现不同类型网络协议的库,如下面的简化示例所示,希望可以说明我遇到的问题。注意:这都是伪代码,只是为了显示整体问题。

class Network
{
  virtual void connect() {...}
  void readPacket() = 0;
};

class NetworkClient : public Network
{
  virtual void connect(int ip, int port) {super::connect() ...}
};

class NetworkServer : public Network
{
  virtual void connect(int port) {super::connect() ...}
};

class ProtocolAClient : public NetworkClient
{
  void readPacket() {...}
};

class ProtocolAServer : public NetworkServer
{
  void readPacket() {...}
};

class ProtocolBClient : public NetworkClient
{
  void readPacket() {...}
};

class ProtocolBServer : public NetworkServer
{
  void readPacket() {...}
};


现在在我的应用程序中,我希望有一个客户端和一个服务器,这应该是一个ProtocolA或ProtocolB客户端/服务器,这取决于用户选择连接哪个协议。

所以我想我可以创建这样的应用程序类。

class AppClient : public NetworkClient
{
   ... custom functionality needed by the app client ...
   void sendAppData(...)
};

class AppServer : public NetworkServer
{
   ... custom functionality needed by the app server ...
   void sendAppData(...)
};


然后我想,当我需要一个客户端时,例如在应用程序中,我可以这样做。

AppClient *client;
if(useProtocalA)
  client = new ProtocolAClient;
else
  client = new ProtocolBClient;
client->sendAppData();


但是,编译器很快就让我知道这是不可能的,因为ProtocolAClient和ProtocolBClient不是AppClient。这是确切的编译器错误。

error C2440: '=' : cannot convert from 'ProtocolAClient *' to 'AppClient *'


因此,我的下一个想法是制作AppClient和AppServer模板类,但这也不起作用,因为您无法获得指向实例的指针,因为该指针没有这样的模板参数。

AppClient *client; <--- Uh oh... missing template argument!
if(useProtocalA)
  client = new AppClient<ProtocolAClient>;
else
  client = new AppClient<ProtocolBClient>;
client->sendAppData();


看来应该解决的问题很简单,但我似乎看不到解决方案。

最佳答案

因此,您有以下课程:

class Network
{
  virtual void connect() {...}
  void readPacket() = 0;
}

class NetworkClient : public Network
{
  virtual void connect(int ip, int port) {super::connect() ...}
}

class AppClient : public NetworkClient
{
   ... custom functionality needed by the app client ...
   void sendAppData(...)
}

class ProtocolAClient : public NetworkClient
{
  void readPacket() {...}
}

class ProtocolBClient : public NetworkClient
{
  void readPacket() {...}
}


问题是您需要一个AppClient对象,但是ProtocolAClientNetworkClient类型的,而不是AppClient类型的。

您的继承如下所示:

Network ---- NetworkClient ---- ProtocolAClient
                          |---- ProtocolBClient
                          |---- AppClient


如您所见,ProtocolAClientProtocolBClient都不是AppClient类型,但是它们全部都是NetworkClient类型。

因此,如果您希望此代码起作用:

AppClient *client;
if(useProtocalA)
  client = new ProtocolAClient;
else
  client = new ProtocolBClient;
client->sendAppData();


您将必须执行以下更改之一:

A)更改您的ProtocolAClientProtocolBClient以继承AppClient类:

class ProtocolAClient : public AppClient
{
  void readPacket() {...}
}

class ProtocolBClient : public AppClient
{
  void readPacket() {...}
}


现在,您的继承如下所示:

Network ---- NetworkClient ---- AppClient ---- ProtocolAClient
                                         |---- ProtocolBClient


或B)-推荐:请勿使用AppClient,因为您已经拥有NetworkClient:

NetworkClient*client;
if(useProtocalA)
  client = new ProtocolAClient;
else
  client = new ProtocolBClient;
client->sendAppData();

关于c++ - C++从多个选择实例化子类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28161419/

10-11 17:55