Server 클래스 설계중 virtual 함수에 대한 의문

Server 클래스 설계중 virtual 함수에 대한 의문

2023년 7월 16일
c++

의문점 발생 #

Server 클래스 구조 설계를 위해 몇가지 방법을 생각해봤다.

  1. Server 클래스를 구현 후 IRCServer 클래스에서 상속받기
  2. SocketServer, IRCServer 를 구현 후 Server 클래스에서 두 클래스를 적절히 사용해서 구현
  3. IRCManager 클래스를 싱글톤으로 생성한뒤 Server 클래스에서 호출

2번은 프로젝트의 구조로 매력을 못느꼈고, 아마 3번은 다른프로젝트때 써볼 가능성이 있을것같아서 상속구조를 혼자서 생각해보기 위해 1번을 선택하던 중 virtual 함수에 대한 의문이 들었다.


부모 클래스 메소드에서 자식클래스 오버라이딩한 함수를 호출할 수 있나? #

 1class Parent {
 2public:
 3	virtual void Hello() { cout << "Hello P" << endl; }
 4	void Test() {
 5               cout << "test Function" << endl;
 6               Hello();           // 부모클래스의 메소드에서 호출하면 누가 호출될까?
 7        }
 8};
 9
10class Child : public Parent {
11public:
12	virtual void Hello() { cout << "Hello C" << endl; }
13};
14
15int main() {
16	Child a;
17	Parent* p = &a;
18
19	p->Test();
20}

결과는 자식클래스의 함수가 호출된다.

1test Function
2Hello C

그렇다면 자식클래스 메소드에서 오버라이딩한 부모클래스의 함수를 호출할때도 동일한가? #

 1class Parent {
 2public:
 3	virtual void Hello() { cout << "Hello P" << endl; }
 4	void Test() { cout << "test Function" << endl; Hello(); }
 5};
 6
 7class Child : public Parent {
 8public:
 9	virtual void Hello() { cout << "Hello C" << endl; }
10	void Test2() { this->Parent::Test(); }
11};
12
13int main() {
14	Child a;
15
16	a.Test2();
17}

결과는 같다

1test Function
2Hello C

결론 #

사실 이상할것도 없는게 this 포인터를 기준으로 virtual table을 검색하기 때문에, 이미 만들어진 부모의 메소드라 해도 오버라이딩 되어있다면 자식클래스의 메소드가 호출된다.

1		Parent::Hello();
200007FF615B77D7D  mov         rcx,qword ptr [this]
300007FF615B77D84  call        Parent::Hello (07FF615B71744h)
4	}
1		Hello();
200007FF6D4A87D7D  mov         rax,qword ptr [this]
300007FF6D4A87D84  mov         rax,qword ptr [rax]
400007FF6D4A87D87  mov         rcx,qword ptr [this]
500007FF6D4A87D8E  call        qword ptr [rax]
6	}

클래스명을 직접 지정하면 그 함수가 호출되고, 지정하지 않으면 this의 vtable에서 가져온다. 이상한게 둘다 필요없는 this를 한번 더 가져오는 작업이 있다.


채택한 방법 #

Server 클래스를 구현 후 IRCServer 클래스에서 상속받기 #

Server 클래스에서는 브로드캐스팅이나 메시지 반사 기능을 수행하는 Execute 함수를 구현하고, Execute를 Run에서 실행시킨다.
IRCServer 클래스는 Server 클래스를 상속받은 후 Execute 함수만 오버라이딩 한다. 아마 맞물려서 정상적으로 동작할것이라고 예상할 수 있다.
-> 정리 필요

comments powered by Disqus