C++ 쓰레드 활용 클래스 오버라이딩 문제
      글쓴이: MyAbby / 작성시간: 일, 2013/08/18 - 11:54오후    
  
  안녕하세요.
소켓을 클래스화 시켜서 사용하고 싶어 만든 소스가 있습니다.
생성자에서 소켓을 생성하고, bind 해서 듣거나 접속하는 형태로 만들고 있는데, 이벤트 처리가 문젭니다.
onConnection_request()와 onData_receive() 더미함수를 만들어 놓고 자식 클래스에서 오버라이딩 시켜 원하는 처리를 할 수 있게 만들고 싶습니다.
근데 자식클래스에서 오버라이딩을 시켜도 원래 선언했던 더미함수가 실행됩니다... 왜이럴까요. 컴파일러 문제일까요?
연결이 들어오면: start_listen_thread() - *listen_thread_func() - onConnection_request()
이렇게 흘러갑니다. 자식, 부모의 this 값을 찍어보면 모두 동일하게 나오는데 왜 오버라이딩이 되지 않을까요?
class Socket : public UserSocket
{
public: void onConnection_request(const int fd, sockaddr_in addr) {}
public: Socket() : UserSocket("tcp") {}
}이런 식으로 오버라이딩 시켰습니다...
아래는 클래스 소스구요. 도와줍쇼~
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
 
class UserSocket
{
	public:
		//Call back events
		//콜백 이벤트
		void onData_receive(const int dataSize, const char *data){}
		void onClose(){}
		void onConnection_request(const int fd, const struct sockaddr_in addr){}
		void onAccept(){}
	private:
		//Essential attributes
		//필수 속성들
		int fd = -1; //소켓 번호
		struct sockaddr_in local_addr, remote_addr; //로컬, 상대 주소
		bool sendable = false; //데이터 전송 가능 여부
 
		//Event handlers
		//이벤트 핸들러들
		pthread_t th_listen = 0, th_read = 0;
	public:
		int getFd()
		{
			return fd;
		}
	private:
		static void *listen_thread_func(void *arg)
		{
			class UserSocket us = *(UserSocket*)arg;
			sockaddr_in remote_addr;
			int lst;
			unsigned int SZ_REMOTE_ADDR = sizeof(remote_addr);
			while(true)
			{
				lst = accept(us.getFd(),
						(struct sockaddr*)&remote_addr, &SZ_REMOTE_ADDR);
				if(lst < 0) break;
				us.onConnection_request(lst, remote_addr);
			}
		}
		bool start_listen_thread()
		{
			if(!isGood_to_use()) return false;
 
			if(pthread_create(&th_listen, NULL, listen_thread_func, (void*)this) < 0)
				return false;
			return true;
		}
		static void *receive_thread_func(void *arg)
		{
			class UserSocket us = *(UserSocket*)arg;
			int size;
			char buf[1500];
 
			while(true)
			{
				memset(buf, 0, sizeof(buf));
				size = read(us.getFd(), buf, sizeof(buf));
				if(size <= 0) break;
				us.onData_receive(size, buf);
			}
			us.disconnect();
		}
		bool start_receive_thread()
		{
			if(!isGood_to_use()) return false;
			if(pthread_create(&th_read, NULL, receive_thread_func, (void*)this) < 0)
				return false;
			return true;
		}
	public:
		void lower_str(char *x)
		{
			for(int i=0; x[i]!=0; i++)
			{
				if('A' <= x[i] && x[i] <= 'Z')
					x[i] += 32;
			}
		}
		UserSocket(const char *xProto)
		{
			char *strProto = new char[strlen(xProto) + 1];
			strcpy(strProto, xProto);
 
			int yProto = -1;
			lower_str(strProto);
			if(!strcmp("tcp", strProto))
				yProto = SOCK_STREAM;
			else if(!strcmp("udp", strProto))
				yProto = SOCK_DGRAM;
 
			if(yProto != -1)
				fd = socket(AF_INET, yProto, 0);
			delete strProto;
		}
		~UserSocket()
		{
			if(fd >= 0)
				close(fd);
			if(th_read != 0)
				pthread_join(th_read, NULL);
			if(th_listen != 0)
				pthread_join(th_listen, NULL);
		}
		bool isGood_to_use()
		{
			if(fd < 0) return false;
			return true;
		}
		bool bind_in(const unsigned short xPort)
		{
			if(!isGood_to_use()) return false;
 
			memset(&local_addr, 0, sizeof(local_addr));
			local_addr.sin_family = AF_INET;
			local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
			local_addr.sin_port = htons(xPort);
 
			if(bind(fd, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0)
				return false;
			return true;
		}
		bool bind_in(const char *xAddr, const unsigned short xPort)
		{
			if(!isGood_to_use()) return false;
 
			memset(&local_addr, 0, sizeof(local_addr));
			local_addr.sin_family = AF_INET;
			local_addr.sin_addr.s_addr = inet_addr(xAddr);
			local_addr.sin_port = htons(xPort);
 
			if(bind(fd, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0)
				return false;
			return true;
		}
		bool listen_in()
		{
 
			if(!isGood_to_use()) return false;
 
			if(listen(fd, 5) < 0) return false;
			return start_listen_thread();
		}
		bool accept_in(const int xFd, const struct sockaddr_in xAddr)
		{
			fd = xFd;
			memcpy(&remote_addr, &xAddr, sizeof(sockaddr_in));
			if(start_receive_thread())
			{
				sendable = true;
				onAccept();
				return true;
			}
			return false;
		}
		bool getSendable()
		{
			return sendable;
		}
		bool sendData(const char *xData, unsigned int xLen)
		{
			if(!getSendable()) return false;
			if(write(fd, xData, xLen) < 0) return false;
			return true;
		}
		void disconnect()
		{
			if(!isGood_to_use()) return;
			close(fd); fd = -1;
			onClose();
		}
};Forums: 


UserSocket(부모 클래스)에서 해당 함수를 virtual로 선언해야죠.
class UserSocket { public: //Call back events //콜백 이벤트 virtual void onData_receive(const int dataSize, const char *data){}www.gilgil.net
죄송해요.. 변화 없습니다.
virtual을 달아 봤지만 여전히 오버라이딩이 안됩니다. 원래 virtual 키워드가 없어도 오버라이드 되는게 정상 아닌가요?
아마 쓰레드를 사용해서 객체가 2개가 된게 아닌듯 싶습니다.. 으이; 뭐지
윈도우에서 dev c로 테스트 만들어봤는데요
이런 결과가 나오네요.
전 그냥 편하게 이런 방식으로 개발합니다. ㅇ_ㅇ;;
//http://no1rogue.blog.me/30096664831
#include <cstdlib> #include <iostream> #include <process.h> //_beginthreadex using namespace std; unsigned int __stdcall td(void* arg); class UserSocket { public: //friend class CSocket; void* pmain; void fn_setMain(void* p) { pmain = p; } void onConnection_request(const int fd) { printf("UserSocket - onConnection_request(%d)\n", fd); } UserSocket(const char *xProto) { printf("UserSocket\n"); } ~UserSocket() { printf("~UserSocket\n"); } private: unsigned int id; //static unsigned int __stdcall td(void* arg); // pthread_t th_listen = 0, th_read = 0; private: static void *listen_thread_func(void *arg) { /* class UserSocket us = *(UserSocket*)arg; sockaddr_in remote_addr; int lst; unsigned int SZ_REMOTE_ADDR = sizeof(remote_addr); while(true) { lst = accept(us.getFd(), (struct sockaddr*)&remote_addr, &SZ_REMOTE_ADDR); if(lst < 0) break; us.onConnection_request(lst, remote_addr); } */ } public: bool start_listen_thread() { printf("UserSocket - start_listen_thread PREV\n"); //argument of type `unsigned int (UserSocket::)(void*)' does not match `unsigned int (*)(void*)' _beginthreadex(NULL, 0, td, pmain, 0, &id); printf("UserSocket - start_listen_thread NEXT\n"); // if(pthread_create(&th_listen, NULL, listen_thread_func, (void*)this) < 0) // return false; return true; } }; class CSocket : public UserSocket { public: // virtual void onConnection_request(const int fd) void onConnection_request(const int fd) { printf("CSocket - onConnection_request(%d)\n", fd); } public: CSocket() : UserSocket("tcp") { printf("CSocket\n"); } ~CSocket() { printf("~CSocket\n"); } void fn_run() { fn_setMain(this); } }; //static unsigned int __stdcall td(void* arg) unsigned int __stdcall td(void* arg) { printf("UserSocket - td PREV\n"); // class UserSocket us = *(UserSocket*)arg; UserSocket* pus = (UserSocket*)arg; if(pus == NULL) { printf("pus is NULL\n"); return 0; } printf("UserSocket - td CENTER\n"); // us.onConnection_request(10); pus->onConnection_request(11); ((CSocket*)pus)->onConnection_request(12); printf("UserSocket - td NEXT\n"); } int main(int argc, char *argv[]) { CSocket s; // s.onConnection_request(1); // ((UserSocket)s).onConnection_request(2); s.start_listen_thread(); ((UserSocket)s).fn_setMain(&s); ((UserSocket)s).start_listen_thread(); printf("---------------------------------\n"); // UserSocket us("test"); // us.start_listen_thread(); system("PAUSE"); return EXIT_SUCCESS; } //출력 결과 UserSocket CSocket UserSocket - start_listen_thread PREV UserSocket - start_listen_thread NEXT ~UserSocket UserSocket - start_listen_thread PREV UserSocket - start_listen_thread NEXT ~UserSocket --------------------------------- UserSocket - td PREV UserSocket - td CENTER UserSocket - onConnection_request(11) CSocket - onConnection_request(12) UserSocket - td NEXT UserSocket - td PREV UserSocket - td CENTER UserSocket - onConnection_request(11) CSocket - onConnection_request(12) UserSocket - td NEXT----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기