継承に基づいて TCP サーバー モデルを作成しようとしましたが、さまざまな成功を収めています。これらのサーバーは、これらのサーバーのシャットダウンとその他の単純なメンテナンス機能をタスクとするシングルトンによって管理されます。
class TCPServer {
public:
TCPServer();
~TCPServer();
void Bind(TCPDaemon *daemon) {
if(!daemon->IsRunning()) {
throw TCPBindException("Daemon is inactive");
}
// if the port is not taken, bind this daemon to it
if(this->servers.count(daemon->port())==0) {
this->servers[daemon->port()]=daemon;
...
} else {
throw TCPBindException("Port is taken");
}
}
void Shutdown() {
MASON::UINT16 i;
for(i=0;i<this->servers.size();i++) {
this->Shutdown((*this->servers.begin()).first);
}
}
void Shutdown(unsigned short port) {
if(this->servers.count(port)) {
if(this->servers[port]->IsRunning()) {
this->servers[port]->Stop();
}
delete this->servers[port];
this->servers.erase(port);
}
}
private:
std::map<unsigned short, TCPDaemon*> servers;
};
TCPDaemon クラスの Stop() 関数は純粋仮想関数です。私の問題は、Shutdown() 関数が呼び出されたときに、派生クラスのバージョンではなく、この純粋な仮想を呼び出そうとしていることです。どうすれば正しいことを強制できますか?
前もって感謝します
[編集] 申し訳ありませんが、以前に TCPDaemon コードを含めていませんでした。これは TCPSocket クラスから派生しています (これは 100% 動作することを確認しており、かなり一目瞭然です)。ここにあります:
class TCPDaemon: public TCPSocket {
public:
TCPDaemon(unsigned short port) {
this->_enabled=false;
this->_host.ipaddr(INADDR_ANY);
this->_host.port(port);
this->paused=false;
struct sockaddr_in opts=this->_host.Compile();
#ifdef PLATFORM_WINDOWS
WSADATA wsaData;
if(WSAStartup(0x0202, &wsaData)) {
throw TCPDaemonException("Failed to start WSA");
}
#endif
this->raw_socket=socket(AF_INET, SOCK_STREAM, 0);
if(this->raw_socket<=0) {
throw TCPDaemonException("Failed to create socket");
}
if(int status=bind(this->raw_socket, (sockaddr*)&opts, sizeof(sockaddr))) {
printf("error [%i]\r\n", status);
throw TCPDaemonException("Failed to bind to port");
}
if(listen(this->raw_socket, 5)) {
throw TCPDaemonException("Failed to listen on port");
}
this->_enabled=true;
}
virtual ~TCPDaemon() {
this->Shutdown();
}
virtual void Start()=0;
virtual void Run(TCPSocket*)=0;
virtual void Stop()=0;
unsigned short port() {
return this->host().port();
}
bool IsRunning() {
return this->_enabled;
}
TCPSocket *Accept() {
SOCKET client;
struct sockaddr client_addr;
int len=sizeof(client_addr);
client=accept(this->raw_socket, &client_addr, &len);
return new TCPSocket(client, &client_addr);
}
void Shutdown() {
}
private:
bool _enabled;
bool paused;
};
サンプルの派生サーバーとその作成方法を次に示します。
class EchoServer: public TCPDaemon {
public:
EchoServer(MASON::UINT16 port): TCPDaemon(port) {
}
~EchoServer() {}
virtual void Start() {
}
virtual void Run(TCPSocket *client) {
printf("RUN\r\n");
Accessor<TCPSocket> acc_client=client;
acc_client->Write(Accessor<Blob> (new Blob(std::string("hello!"))));
acc_client->Disconnect();
}
virtual void Stop() {
}
};
myTCPServer->Bind(new EchoServer(8008));
[編集+1] 問題はこれに要約されると思います(私は簡単に間違っている可能性があります): 私は、純粋な仮想/抽象関数 Stop() を持つ基本クラス TCPDaemon の std::map を持っています。マップ内のエントリの 1 つを介して Stop() を呼び出すと、オーバーライド関数 EchoServer::Stop() ではなく、TCPDaemon::Stop() を呼び出そうとしているようです。これが問題でしょうか?もしそうなら、どうすれば解決できますか?