C++/C++

Effective C++ 객체 생성 및 소멸 과정 중에는 가상 함수를 호출하지 말라

Elan 2021. 6. 27. 00:49

Do not use virtual function in constructor/destructor.

 

class Transaction {
public:
	virtual void logTransaction() const = 0;
};
Transaction::Transaction() {
	logTransaction(); // 하위 객체에서 재정의 했더라도 Transaction::logTransaction이 호출 됨
}

class BuyTransaction : public Transaction {
public:
	virtual void logTransaction() const
	{} // logTransaction 재정의
};

class SellTransaction : public Transaction {
public:
	virtual void logTransaction() const;
};

int main() {
	BuyTransaction b; // error 발생
}

위 코드의 main 함수를 실행하면 BuyTansaction 객체의 생성자가 호출된다.

그런데 이 객체는 상속 구조를 가지고 있으므로

부모 객체의 생성자가 먼저 호출된 후 자식 객체의 생성자가 호출된다.

즉, 생성자 호출 순서는 Transaction() > BuyTransaction() 이다.

그런데!!!

Transaction의 생성자 내부에서 가상 함수 logTransaction()을 호출한다.

사실 C++은 상위 객체 Transaction의 생성자가 끝나기 전에는
절대로 파생 클래스 BuyTransaction의 가상테이블로 내려가지 않는다.

즉, Transaction의 생성자에서 logTransaction()을 호출할 경우

재정의 된(override) 가상 함수 BuyTransactino::logTransaction()을 호출하는 것이 아니라

현재 실행 중인 생성자 Transaction에 해당하는 Transcation::logTranscation()이 호출된다.

따라서,
Transaction의 생성자가 끝나기 전에는, 즉, BuyTransaction의 생성자가 호출되기 전까지는
인스턴스 b의 타입은 Transaction과 마찬가지다.




그러므로 위 코드의 에러 원인은

Transaction 생성자에서 Transaction의 순수 가상 함수를 호출하였기 때문이다.