항목 9 : 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자

2022. 8. 17. 23:06·STUDY/Effective C++

 

class Transaction {
public:
	Transaction();
	virtual void logTransaction() const = 0;
	...
};

Transaction::Transaction() //기본 클래스 생성자
{
	...
	logTransaction();
}

class BuyTransaction: public Transaction { //Transaction의 파생 클래스
public:
	virtual void logTransaction() const;
	...
};
BuyTransaction b;

위와 같은 코드가 있을때 BuyTransaction b; 코드를 작성한다면 호출되는 logTransaction함수는 BuyTransaction의 것이 아니라 Transaction의 것이다.

 

기본클래스의 생성자가 호출 될 동안에는, 가상 함수는 절대로 파생 클래스 쪽으로 내려가지않는다.

( = 기본 클래스 생성과정에서는 가상함수가 먹히지않는다.)

 

왜냐하면 기본 클래스 생성자는 파생 클래스 생성자보다 앞서 실행되기때문에, 기본 클래스 생성자가 돌아가고 있을 시점에는 파생 클래스 데이터 멤버는 아직 초기화된 상태가 아니다.

 

파생클래스(BuyTransaction)만의 데이터가 아직 초기화된 상태가 아니기때문에 아예 없는것으로 취급하는게 안전하다고 생각하기때문에 파생클래스의 객체는 기본 클래스 부분이 생성되는 동안은, 기본 클래스타입의 객체로 취급한다.

 

그리고 C++은 초기화되지 않은 영역을 건드리는 것 자체를 못하도록 막기때문에 가상함수가 파생클래스 쪽으로 내려가지않는다.

 

소멸자 또한 마찬가지로 소멸자가 호출되고나면, C++은 파생 클래스만의 데이터 멤버를 없는것처럼 취급하고 진행한다.

 

 

 

 

이러한 문제점을 해결하기위해서는 어떻게해야할까?

class Transaction {
public:
	explict Transaction(const std::string& logInfo);
	void logTransaction(const std::string& logInfo) const; //비가상 함수
	...
};

Transaction::Transaction(const std::string& logInfo)
{
	...
	logTransaction(logInfo); //비가상 함수 호출
}

class BuyTransaction: public Transaction {
public:
	BuyTransaction(parameters)
	 : Transaction(createLogString (parameters) ) //로그 정보를 기본 클래스 생성자로 넘김
	 {...}
	 ...
     
private:
	static std::string createLogString(parameters);
};

바로 가상함수를 비가상 멤버함수로 바꾸는것이다. 

위의 코드들을 예시로 들자면,

파생클래스의 생성자들이 필요한 로그 정보를 Transaction의 생성자로 넘기면=>

비가상 함수로 바꾼 logTransaction이 안전하게 수행된다. (정적 멤버로도 되어있기때문에 더욱더 안전)

 

필요한 초기화 정보를 파생클래스에서 기본 클래스 생성자로 올려준다는 얘기니

기존에 기본 클래스에서 정의한 가상함수를 파생클래스에서 사용할려고한 의도와 똑같이 사용이 가능하다.

'STUDY > Effective C++' 카테고리의 다른 글

항목 11: operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자  (0) 2022.08.31
항목 10 : 대입 연산자는 *this의 참조자를 반환하게 하자  (0) 2022.08.24
항목 8: 예외가 소멸자를 떠나지 못하도록 붙들어 놓자  (0) 2022.08.17
항목 7: 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자  (0) 2022.06.25
항목 6: 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해버리자  (0) 2022.06.23
'STUDY/Effective C++' 카테고리의 다른 글
  • 항목 11: operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자
  • 항목 10 : 대입 연산자는 *this의 참조자를 반환하게 하자
  • 항목 8: 예외가 소멸자를 떠나지 못하도록 붙들어 놓자
  • 항목 7: 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자
wise_
wise_
  • wise_
    WHY'S BlOG
    wise_
  • 전체
    오늘
    어제
    • 분류 전체보기 (63)
      • PROJECT (19)
        • 젯슨나노 프로젝트 (0)
        • 유니티 (9)
      • STUDY (37)
        • 코딩문제 (13)
        • 알고리즘 (0)
        • Effective C++ (14)
        • 유니티 (8)
        • 언리얼 (2)
      • ERROR (7)
        • 오류덩어리들 (7)
      • REVIEW (0)
      • LIFE (0)
        • 작고 소중한 내 일상 (0)
        • 작고 귀여운 내 취미 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백준
    게임개발
    퍼즐게임
    여우는오늘도친구를구한다
    언리얼
    ==
    유니티
    코딩
    윈터데브캠프
    unity
    모바일게임
    와이즌
    깊이우선탐색
    귀여운
    null
    스마일게이트
    개발일지
    1인개발
    C++
    개발
    힐링
    게임
    wisen
    error
    알고리즘
    인디게임
    TheFoxSeeksFriend
    힐링게임
    플로이드와샬
    c#
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
wise_
항목 9 : 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.