Search Results for '생성자'

1 POSTS

  1. 2006.08.30 생성자에서 가상 함수를 부르지 말자! 2
[Effective C++ (3rd Edition)](Scott Meyers, Addison-Wesley Professional, 2005)에 나오는 “Never Call Virtual Functions during Construction or Destruction”라는 글을 읽었다.

핵심만 간단히 요약하면 C++의 생성자 및 소멸자에서는 가상 함수가 가상 함수로 동작하지 않는다는 거다. 왜냐하면 베이스 클래스 생성자에서는 아직 하위 클래스의 멤버가 초기화되지 않았는데, 하위 클래스의 가상 함수는 하위 클래스의 멤버를 참조하기 때문이다.

C++과는 달리 자바와 C#에는 이런 조치가 없다. 이 경우 어떤 문제가 생기는지 보자

public class Base {
  public Base() {
    System.out.println("Base class");
    virtualFunction();
  }

  public void virtualFunction() {
    System.out.println("Base virtualFunction");
  }
}

public class Sub extends Base {
  public String str = "Hello world!";

  public Sub() {
    System.out.println("Sub class");
    System.out.println(str);
  }

  public void virtualFunction() {
    System.out.println("Sub virtualFunction:" + str);
  }

  public static void main(String ...args) {
    new Sub();   
  }
}


위 자바 코드를 실행시켜보면 다음과 같다.

Base class
Sub virtualFunction:null
Sub class
Hello World!

Base클래스의 생성자에서 부른 virtualFunction이 Sub 클래스의 virtualFunction을 호출하고, 이 메소드는str 멤버를 출력한다. 근데 이때 아직 Sub 클래스의 생성자가 불리지 않은 상태이므로, str는 초기화되지 않은 null값을 출력한다. 즉 의도하지 않게 아직 초기화되지 않은 값을 참조하게 되는 것이다.

C++의 경우 Base클래스에서 virtualFunction이 더 이상 가상 함수가 아닌 것으로 보고 Base 클래스의 virtualFunction을부르는 방식으로 이 문제를 해결한다. 하지만 Scott Meyers의 말처럼 생성자나 소멸자에서 가상 함수를 부르지 않는 편이안전하다.