Другой пример полиморфного поведения: C++ и C#
Я попробовал следующий пример на C++. Я понял, что переопределение Method4() из класса CA с использованием Method4(int a) в CB скрывает Method4() только с точки зрения видимости, а не с точки зрения VMT. Поэтому первые два вызова функции Main не работают.
class CA
{
public:
virtual void Method1() { }
virtual void Method2() { }
virtual void Method3() { }
virtual void Method4() { }
};
class CB : public CA
{
public:
void Method1() { }
void Method2() { }
void Method4(int a) { }
};
int main()
{
CB b1;
b1.Method4(); // IT'S NOT WORKING (I EXPECTED)
CB* b2 = new CB;
b2->Method4(); // IT'S NOT WORKING (I EXPECTED)
CA* a = new CB;
a->Method4(); // IT'S WORKING (I EXPECTED)
return 0;
}
Я попытался воспроизвести пример на C#. К моему удивлению, следующий вызов совершенно нормальный.
CB b1 = new CB(); // I EXPECTED NOT TO WORK, BUT IT DOES WORK
b1.Method4();
Мой вопрос: почему? Это реальная разница между двумя языками или я что-то упускаю?
Следуя вашим справедливым предложениям, я добавил код C# ниже:
public class CA
{
public virtual void Method1() { }
public virtual void Method2() { }
public virtual void Method3() { }
public virtual void Method4() { }
}
public class CB : CA
{
public override void Method1() { }
public override void Method2() { }
public void Method4(int a) { }
}
public static void Main()
{
CB b = new CB(); // IT'S WORKING (I DIDN'T EXPECT THIS)
b.Method4();
}
1 ответ
Я понял, что переопределение Method4() из класса CA с использованием Method4(int a) в CB скрывает Method4().
Не на С#.Method4()
иMethod4(int a)
имеют разные подписи, поэтому с точки зрения наследования они похожи на разные методы.
В С# есть концепция сокрытия, но она другая:
class CA{
public void Method(){Console.WriteLine("CA");}
}
class CB : CA{
public new void Method(){Console.WriteLine("CB");}
}
В этом случае вызываемый метод будет зависеть от типа ссылки. Таким образом, CB.Method «скроет» CA.Method. Это ясно выражено вnew
ключевое слово, если его пропустить, будет выдано предупреждение.