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

의문점 발생

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

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

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

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

class Parent {
public:
	virtual void Hello() { cout << "Hello P" << endl; }
	void Test() {
               cout << "test Function" << endl;
               Hello();           // 부모클래스의 메소드에서 호출하면 누가 호출될까?
        }
};

class Child : public Parent {
public:
	virtual void Hello() { cout << "Hello C" << endl; }
};

int main() {
	Child a;
	Parent* p = &a;

	p->Test();
}

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

test Function
Hello C

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

class Parent {
public:
	virtual void Hello() { cout << "Hello P" << endl; }
	void Test() { cout << "test Function" << endl; Hello(); }
};

class Child : public Parent {
public:
	virtual void Hello() { cout << "Hello C" << endl; }
	void Test2() { this->Parent::Test(); }
};

int main() {
	Child a;

	a.Test2();
}

결과는 같다

test Function
Hello C

결론

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

		Parent::Hello();
00007FF615B77D7D  mov         rcx,qword ptr [this]
00007FF615B77D84  call        Parent::Hello (07FF615B71744h)
	}
		Hello();
00007FF6D4A87D7D  mov         rax,qword ptr [this]
00007FF6D4A87D84  mov         rax,qword ptr [rax]
00007FF6D4A87D87  mov         rcx,qword ptr [this]
00007FF6D4A87D8E  call        qword ptr [rax]
	}

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

채택한 방법

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

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

Comments

ESC
Type to search...