Здравствуйте, igna, Вы писали: I>А польза какая от решения принятого в C#, ну то есть от того, что конструктор базового класса вызывает виртуальную функцию производного класса?
Никакой специальной пользы нет, как и вреда.
Просто другая архитектура. Тип объекта никогда не меняется в течение его жизни. А в С++ объект при создании/разрушении проходит всю эволюционную цепочку. В управляемой среде так делать просто нельзя — например, если в конструкторе какого-либо из классов в цепочке наследования произойдет исключение, тип объекта должен быть правильным.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Там написано "...виртуальность не может быть корректно разрешена, по крайней мере так дело обстоит с С++", а это неверно. В C++ виртуальность разрешается в пользу функции базового класса.
I>Там написано "...виртуальность не может быть корректно разрешена, по крайней мере так дело обстоит с С++", а это неверно. В C++ виртуальность разрешается в пользу функции базового класса.
Ну вот с точки зрения .NET это некорректное поведение
Здравствуйте, igna, Вы писали: I>Ну да. А корректное с точки зрения .NET поведение приводит к появлению советов вроде "Do not call overridable methods in constructors".
Позволю себе напомнить, что вызов виртуальных методов из конструкторов в C++ также является порочной практикой.
И ровно по той причине, что виртуальность работает не так, как в других методах. Так что хрен редьки не слаще.
Классической задачкой на понимание неочевидностей процесса конструирования объекта в C++ является вопрос "можно ли произвести вызов абстрактного метода без хаков с кастом?".
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, rsn81, Вы писали:
R>Здравствуйте, <Аноним>, Вы писали:
А>>А разве инициализация полей дефолтовыми значениями происходит не до выполнения конструктора? R>Не до завершения родительского конструктора.
след. пример показывает, что вы ошибаетесь:
class Program
{
static void Main(string[] args) {
new Derived();
Console.ReadLine();
}
}
class Base
{
public Base() {
Console.WriteLine(string.Format("i = {0}", this.GetType().GetField("i").GetValue(this)));
Console.WriteLine("Base .ctor end");
}
}
class Derived : Base
{
public int i = 3;
Здравствуйте, vensub, Вы писали:
V>след. пример показывает, что вы ошибаетесь:
[skipped]
Интересно. Гм... и странно, если ничего не напутали. Под рукой студии нет, проверил тоже самое в Java:
package ru.rsdn.init;
public class Base {
public Base() {
try {
System.out.println("base.ctor: " +
getClass().getField("i").getInt(this));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
package ru.rsdn.init;
public class Derived extends Base {
public final int i = 1;
public Derived() {
System.out.println("derived.ctor: " + i);
}
public static void main(String... args) {
new Derived();
}
}
Здравствуйте, rsn81, Вы писали:
R>Интересно, ведь получается, что в .NET таким образом автоматически частично решается обсуждаемая в теме проблема...
Частично -- да, если инициализация производного класса совсем простая. Но одновременно добавляется тонкий аспект поведения, о котором нужно помнить.
Re[12]: Virtual member call in constructor. Плохо?
Здравствуйте, Mab, Вы писали:
Mab>Частично -- да, если инициализация производного класса совсем простая. Но одновременно добавляется тонкий аспект поведения, о котором нужно помнить.
Смотрю сейчас язык Scala под JVM. Вот такой класс: