Re[2]: Virtual member call in constructor. Плохо?
От: igna Россия  
Дата: 02.11.07 11:37
Оценка:
Здравствуйте, nikov, Вы писали:

N>Do not call overridable methods in constructors


Значит прав был Страуструп. В C++ при выполнении конструктора базового класса вызывается виртуальная функция базового класса.

А польза какая от решения принятого в C#, ну то есть от того, что конструктор базового класса вызывает виртуальную функцию производного класса?
Re[3]: Virtual member call in constructor. Плохо?
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 02.11.07 11:51
Оценка:
Здравствуйте, igna, Вы писали:

Здесь Re: Virtual member call in constructor. Плохо?
Автор: denezuela
Дата: 30.10.07
и ниже.
Re[3]: Virtual member call in constructor. Плохо?
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.11.07 12:17
Оценка: 11 (3) +1
Здравствуйте, igna, Вы писали:
I>А польза какая от решения принятого в C#, ну то есть от того, что конструктор базового класса вызывает виртуальную функцию производного класса?
Никакой специальной пользы нет, как и вреда.
Просто другая архитектура. Тип объекта никогда не меняется в течение его жизни. А в С++ объект при создании/разрушении проходит всю эволюционную цепочку. В управляемой среде так делать просто нельзя — например, если в конструкторе какого-либо из классов в цепочке наследования произойдет исключение, тип объекта должен быть правильным.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Virtual member call in constructor. Плохо?
От: igna Россия  
Дата: 02.11.07 12:22
Оценка:
Здравствуйте, rsn81, Вы писали:

R>Здесь Re: Virtual member call in constructor. Плохо?
Автор: denezuela
Дата: 30.10.07
и ниже.


Там написано "...виртуальность не может быть корректно разрешена, по крайней мере так дело обстоит с С++", а это неверно. В C++ виртуальность разрешается в пользу функции базового класса.
Re[5]: Virtual member call in constructor. Плохо?
От: Mab Россия http://shade.msu.ru/~mab
Дата: 02.11.07 12:36
Оценка:
Здравствуйте, igna, Вы писали:


I>Там написано "...виртуальность не может быть корректно разрешена, по крайней мере так дело обстоит с С++", а это неверно. В C++ виртуальность разрешается в пользу функции базового класса.

Ну вот с точки зрения .NET это некорректное поведение
Re[6]: Virtual member call in constructor. Плохо?
От: igna Россия  
Дата: 02.11.07 12:47
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Ну вот с точки зрения .NET это некорректное поведение


Ну да. А корректное с точки зрения .NET поведение приводит к появлению советов вроде "Do not call overridable methods in constructors".
Re[7]: Virtual member call in constructor. Плохо?
От: Sinclair Россия https://github.com/evilguest/
Дата: 06.11.07 05:58
Оценка:
Здравствуйте, igna, Вы писали:
I>Ну да. А корректное с точки зрения .NET поведение приводит к появлению советов вроде "Do not call overridable methods in constructors".
Позволю себе напомнить, что вызов виртуальных методов из конструкторов в C++ также является порочной практикой.
И ровно по той причине, что виртуальность работает не так, как в других методах. Так что хрен редьки не слаще.
Классической задачкой на понимание неочевидностей процесса конструирования объекта в C++ является вопрос "можно ли произвести вызов абстрактного метода без хаков с кастом?".
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: Virtual member call in constructor. Плохо?
От: vensub Украина  
Дата: 06.11.07 08:42
Оценка:
Здравствуйте, 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;

public Derived() {
Console.WriteLine(string.Format("i = {0}", i));
Console.WriteLine("Derived .ctor");
}
}
Re[6]: Virtual member call in constructor. Плохо?
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 06.11.07 09:54
Оценка:
Здравствуйте, 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();
    }
}
Получил в консоли:

base.ctor: 0
derived.ctor: 1

Re[7]: Virtual member call in constructor. Плохо?
От: Mab Россия http://shade.msu.ru/~mab
Дата: 06.11.07 09:57
Оценка: +1
Здравствуйте, rsn81, Вы писали:

В .NET код, инициализирующий члены, вставляется до вызова конструктора базового класса.
Re[8]: Virtual member call in constructor. Плохо?
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 06.11.07 10:12
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>В .NET код, инициализирующий члены, вставляется до вызова конструктора базового класса.

То есть это:
class A {
    public A() {
    }
}

class B: A {
    private readonly object obj = new object();
    
    public B() {
    }
}
сгенерируется в иной MSIL-код, нежели вот это
class B: A {
    private readonly object obj;
    
    public A() {
        obj = new object();
    }
}
?
Re[9]: Virtual member call in constructor. Плохо?
От: Mab Россия http://shade.msu.ru/~mab
Дата: 06.11.07 10:16
Оценка: 8 (1)
Здравствуйте, rsn81, Вы писали:

Да. Будет
.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       21 (0x15)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void A::.ctor()
  IL_0006:  nop
  IL_0007:  nop
  IL_0008:  ldarg.0
  IL_0009:  newobj     instance void [mscorlib]System.Object::.ctor()
  IL_000e:  stfld      object B::obj
  IL_0013:  nop
  IL_0014:  ret
} // end of method B::.ctor

и
.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       21 (0x15)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  newobj     instance void [mscorlib]System.Object::.ctor()
  IL_0006:  stfld      object B::obj
  IL_000b:  ldarg.0
  IL_000c:  call       instance void A::.ctor()
  IL_0011:  nop
  IL_0012:  nop
  IL_0013:  nop
  IL_0014:  ret
} // end of method B::.ctor

соответственно.
Re[10]: Virtual member call in constructor. Плохо?
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 06.11.07 10:25
Оценка:
Здравствуйте, Mab, Вы писали:

Забавно.
Интересно, ведь получается, что в .NET таким образом автоматически частично решается обсуждаемая в теме проблема...
Re[11]: Virtual member call in constructor. Плохо?
От: Mab Россия http://shade.msu.ru/~mab
Дата: 06.11.07 10:29
Оценка:
Здравствуйте, rsn81, Вы писали:

R>Интересно, ведь получается, что в .NET таким образом автоматически частично решается обсуждаемая в теме проблема...

Частично -- да, если инициализация производного класса совсем простая. Но одновременно добавляется тонкий аспект поведения, о котором нужно помнить.
Re[12]: Virtual member call in constructor. Плохо?
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 14.11.07 09:52
Оценка:
Здравствуйте, Mab, Вы писали:

Mab>Частично -- да, если инициализация производного класса совсем простая. Но одновременно добавляется тонкий аспект поведения, о котором нужно помнить.

Смотрю сейчас язык Scala под JVM. Вот такой класс:
package ru.rsdn;

class MyClass[P](property: P) {
  def getProperty() = property
}
компилируется в такой вот байт-код:
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) braces deadcode fieldsfirst splitstr(80) nonlb space lnc 
// Source File Name:   MyClass.scala

package ru.rsdn;

import scala.ScalaObject;

public class MyClass implements ScalaObject {
    private Object property;

    public MyClass(Object property) {
        this.property = property;
        super();
    }

    public Object getProperty() {
        return property;
    }

    public int $tag() {
        return scala.ScalaObject.class.$tag(this);
    }
}
Смотрю внимательно на конструктор и думаю, почему все понимают суть проблемы, а Sun — нет?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.