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의 순수 가상 함수를 호출하였기 때문이다.