안녕하세요.
최근에 아래와 같은 문제를 접했는데, 답이 제 예상과 다르네요.
저는 int 형의 값이 전달되었으니 당연히 "Derived.Func(int)" 가 출력될 줄 알았으나,
실제는 "Derived.Func(object)" 가 출력되었습니다.
어떤 이유인가 알고 싶어서 코파일럿에게 소스코드와 실행결과를 물어보니 저와 같은 답변을 출력하네요.
"Derived.Func(object)" 가 출력되는 이유에 대해서 아시는 분은 말씀 부탁드립니다.
감사합니다.
using System;
namespace _12_ConsoleApp
{
public class Program
{
static void Main(string[] args)
{
Derived d = new Derived();
int i = 10;
d.Func(i);
Console.ReadKey();
}
}
public class Base
{
public virtual void Func(int x)
{
Console.WriteLine("Base.Func(int)");
}
}
public class Derived : Base
{
public override void Func(int x)
{
Console.WriteLine("Derived.Func(int)");
}
public void Func(object o)
{
Console.WriteLine("Derived.Func(object)");
}
}
}
첫댓글 안녕하세요. 이게 답변이 될지는 모르지만, 저도 눈으로 보면 문의하신 망고님의 결과물이 나올줄로 알았습니다. 나름 검색을 하니 아래와 같다고 하니 도움이 되길 바랍니다
"컴파일러는 d.Func(i)를 처리할 때, 정적 타입인 int와 가장 일치하는 메서드를 찾습니다. 하지만 Derived 클래스에서 오버라이딩된 Func(int)가 부모 클래스 메서드의 일부로 묶여 있다고 간주되며, 독립적인 오버로드 메서드 Func(object)가 우선됩니다."
override 된 함수를 호출하고자 한다면, ((Base)d).Func(i); 형변환하여 명시화해서 호출하는것을 제안드립니다.
답변 감사합니다. 지금까지는 단순히 C# 문법만 봤는데, 이제는 컴파일러 동작까지도 공부해야겠네요. 덕분에 좀 더 배웠습니다~
@망고 저도 덕분에 많이 배웠습니다. 일반 상속도 좋지만, abstract 클래스로 상속하여 강제화하여 자식 클래스에서 override 하면 제대로 저희 지식으로 알고 있는 public override void Func(int x) 로 호출이 가능해 보입니다. 미리 새해 복 많이 받으세요.
함수 호출 순서가 있습니다. C# 관련 강의중에 상속 편을 보시면... 이해가 쉬우실텐데요.
Base.Func는 가상함수.
Derived.Func는 상속받아 재정의한 함수.
이때 객체 Derived타입으로 생성하셨고 해당 멤버의 Func을 호출 하셨으니
Derived.Func을 호출 하게 됩니다.
public class Derived : Base
{
public override void Func(int x)
{
base.Func(x); // 이렇게 하시면 상위 객체 Base.Func을 호출 한 후 진행이 됩니다.
Console.WriteLine("Derived.Func(int)");
}
}
그럼 또 하나 해보셔야 할 것은.
객체 생성을
Base d = new Derived(); // 이렇게 d로 생성하였을때 어디부터 호출이 될까요?
//Base.Func 이 호출되지만 가상이니 생성된 객체타입의 재정의된 Func까지 호출순서를 옮겨서 먼저 호출하게 됩니다.
C++ 포인터랑 메모리 관련해서 배우시면 좀 더 이해가 편하실거구요.
아참... 지나가는길에 추가 하자면...
클래스를 한단계 더 상속해서 브레이크 걸고 테스트 해보세요.
Base
Derived : Base
OneMoreDownDerived : Derived