2021
04.26

다음 본문은 도서 이펙티브 C# (빌 와그너)에서 나오는 주제를 다룹니다.

 

 

상속된 클래스의 생성자는 꽤 주의해서 다루어야 한다.

2021.04.26 - [C# Study/C# 케이스 스터디] - C# 상속 클래스 부모의 생성자 호출 순서

 

상속 클래스가 인스턴스화 될 때 부모의 생성자가 먼저 호출된다. 

그런데 부모 생성자 내에서 호출하는 함수가 가상 함수(virtual)로 지정되어있고,

이를 자식 클래스에서 오버라이딩한 경우를 생각해보자.

 

public class TestScript : MonoBehaviour
{
    [Button]
    public void Test()
    {
        var Temp = new B("test");
    }
}

public class A
{
    public A()
    {
        Debug.Log("A");
        MyMethod();
    }

    public virtual void MyMethod()
    {
        Debug.Log("부모 클래스의 가상함수");
    }
}

public class B : A
{
    public B(string str)
    {
        Debug.Log($"B {str}");
    }

    public override void MyMethod()
    {
        Debug.Log("자식 클래스의 오버라이딩 함수");
    }
}

 

먼저 부모 클래스의 생성자가 호출되고, 부모 생성자 내에서 가상 함수가 호출되며,

이 가상 함수는 자식이 오버라이딩했으니 오버라이딩된 함수가 호출된다.

 

이 시점에서 자식 클래스의 생성자가 완료되지 않았지만 자식클래스의 함수를 호출하였다.

 

생성자가 완료되기 전까지는 객체가 완전히 생성된 것이 아니다. 때문에

1) 생성자 내에서 가상 함수를 호출하면 이상 동작을 일으킬 수 있으며,

2) 자식 클래스마다 구현한 가상 함수에 따라 부모의 생성자가 바뀌기 때문에 일관성이 없다.

 

C++과 C#의 차이

C++과 C#에서는 동작이 다르다.
C++에서는 각 클래스의 생성자가 실행되면 객체의 런타임 타입이 변경된다.
C#에서는 런타임을 고려하여 함수를 호출한다.

부모 생성자에서 추상 함수를 호출한다면 C++은 런타임 오류가 발생하지만, 

C#은 정상적으로 자식의 오버라이딩 함수가 호출될 것이다.

 

결론

 - 생성자 내에서는 가급적 가상 함수를 호출하지 말자.

 - 자식 클래스의 생성자는 부모 클래스의 기본 생성자 이후에 호출된다는 점을 기억할 것. 

 

 

 

COMMENT