Я пытался создать модель 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;
};
Функция Stop () класса TCPDaemon является чисто виртуальной.Моя проблема в том, что когда вызывается функция 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] Я думаю, что проблема сводится к следующему(я легко могу ошибаться): у меня есть std :: map базового класса, TCPDaemon, который имеет чисто виртуальную / абстрактную функцию Stop ().Похоже, что когда я вызываю Stop () через одну из записей на карте, он пытается вызвать TCPDaemon :: Stop (), а не переопределяющую функцию EchoServer :: Stop ().Может ли это быть проблемой?Если так, как я могу решить это?