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로 선언해야죠.
www.gilgil.net
죄송해요.. 변화 없습니다.
virtual을 달아 봤지만 여전히 오버라이딩이 안됩니다. 원래 virtual 키워드가 없어도 오버라이드 되는게 정상 아닌가요?
아마 쓰레드를 사용해서 객체가 2개가 된게 아닌듯 싶습니다.. 으이; 뭐지
윈도우에서 dev c로 테스트 만들어봤는데요
이런 결과가 나오네요.
전 그냥 편하게 이런 방식으로 개발합니다. ㅇ_ㅇ;;
//http://no1rogue.blog.me/30096664831
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기