Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [Все]   Вниз
  Печать  
Автор Тема: Виртуальные конструкторы  (Прочитано 44492 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Лёха
Гость
« : 07-09-2008 16:05 » 

Всем доброго время суток.
Все вы наверняка читали книжки и знаете что виртуальных конструкторов быть не может. Виртуальные деструкторы - обычная правильная конструкция. Исходя из того что, деструкторы могут быть виртуальными, почему конструкторы не могут быть таковыми ?

В случае с деструкторами:
class A
{
public:
   A(){    cout << "A()\n";           };
   ~A(){  cout << "~A()\n";   };
};

class B : public A
{
public:
   B(){     cout << "B()\n";      };
   ~B(){   cout << "~B()\n";   };
};


int main(void)
{
   A * a = new B();
   delete a;
}

результат
 A()
 B()
 ~A()

результат если юзать virtual ~A()
 A()
 B()
 ~B()
 ~A()

В данном случае компилер предпологает что а - указывает на объект А а не на В, и без явного преобразования невозможно вызвать мембер класса В посредствам указателя а.

В случае с конструкторами (если бы можно было так):
результат бы был
 A()
 ~A()

и/или конструкция типа ((В*)а)->someMember не допускалась бы

результат если юзать виртуальный конструктор (virtual A())
 A()
 B()
 ~B()
 ~A()


Конечно всё это не имеет смысла, но вопрос в том почему стандарт не принял того, что при наследовании использовать виртуальный деструктор по умолчанию. Я просто пытаюсь понять почему конструктор не может быть виртуальным.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 07-09-2008 17:04 » 

Цитата
В данном случае компилер предпологает что а - указывает на объект А а не на В, и без явного преобразования невозможно вызвать мембер класса В посредствам указателя а.
неверное утверждение, компилятор понятия не имеет, на что указывает a. Вернее имеет - он указывает на экземпляр класса A, просто этот класс имеет таблицу виртуальных функций, которые будут вызваны из класса B, так как именно адрес такого экземпляра был присвоен указателю a


Цитата
Исходя из того что, деструкторы могут быть виртуальными, почему конструкторы не могут быть таковыми ?
видимо, в этом нет смысла, так как можно не знать, для чего вызывать ДЕСТРУКТОР, но ты всегда знаешь, экземпляр КАКОГО класа создаёшь - на стеке ли или через new. Всегда тип указан.
В общем - для начала придумай примеры использования виртуального конструктора Улыбаюсь
Записан

McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #2 : 07-09-2008 18:00 » 

1. Нет никакого смысла в виртуальных конструкторах.
2. оформляй свой код тегами [ code ] [ /code ]
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 07-09-2008 18:54 » 

Цитата: Лёха
Я просто пытаюсь понять почему конструктор не может быть виртуальным.
Потому что конструктор создаёт объект, а в C++-образных языках имя конструктора совпадает с именем класса. Моменты создания и инициализации объекта в таких языках совпадают. Поскольку до вызова конструктора объекта ещё нет, то вызов какого-либо конструктора приводит к созданию объекта именно того класса, в котором определён конструктор.

Код: (C++)
...
class X {};
class Y: public X {};
// создали объект класса X и вызвали конструктор по умолчанию подкласса Y,
// иначе автоматически вызовется конструктор не того класса.
X x = Y();
...

Так же обстоит дело в нетипизированных языках.
Код: (Javascript)
...
// Конструктор объектов типа X.
function X() {
}

/*
 * Переменная не имеет типа, тип X имеет лишь значение перемеменной - созданный при помощи
 * конструктора объект.
 */

var x = new X();
...

А вот в том же Object Pascal, где конструктор - не более чем разновидность рядовой процедуры, дело обстоит иначе. В этом языке синтаксически различается момент создания объекта определённого типа (выделение памяти под него) и момент вызова конструктора как процедуры инициализации созданного объекта начальными значениями. Поэтому виртуальные конструкторы в Object Pascal смысл имеют.
Код: (Text) Object Pascal
...
type
  TX = class
     ...
  end;
  TY = class(TX)
     ...
  end;
var
   PX: ^TX; { объявление указателя типа TX  }
   Y: TY; { объявление переменной типа TY и создание объекта типа TY до начала выполнения кода }
begin
   PX := @Y;
   PX^.Сreate; { вызов конструктора объекта для инициализации начальными значениями }
...
Хотя обычно пользуются выражениями типа:
Код: (Text) Object Pascal
...
Y := TY.Create; { явное указание класса конструктора }
...

Цитата: McZim
1. Нет никакого смысла в виртуальных конструкторах.
Ты "в корне не прав" (c) Улыбаюсь Шаблон проектирования "фабричный метод" имеет второе название "виртуальный конструктор". Виртуальный конструктор инкапсулирует механизм создания конкретной разновидности объекта какого-либо класса, когда нам нужно абстрагироваться от этого механизма и связанного с ним разнообразния конкретных разновидностей (подклассов).
Код: (C++)
class A {};
enum Selector { SB, SC };
class B: public A {};
class C: public A {};

// Виртуальный конструктор
A *СreateA(Selector selector) {
   switch(selector) {
   case SB:
      return new B();
   case SC:
      return new C();
   default:
      return NULL;
   }
}
« Последнее редактирование: 07-09-2008 19:53 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #4 : 07-09-2008 20:16 » 

Цитата
Узнав о виртуальных деструкторах, естественно спросить: "Могут ли
      конструкторы то же быть виртуальными?" Если ответить коротко - нет.
      Можно дать более длинный ответ: "Нет, но можно легко получить
      требуемый эффект".
      Конструктор не может быть виртуальным, поскольку для правильного
      построения объекта он должен знать его истинный тип. Более того,
      конструктор - не совсем обычная функция. Он может взаимодействовать
      с функциями управления памятью, что невозможно для обычных
      функций. От обычных функций-членов он отличается еще тем, что
      не вызывается для существующих объектов. Следовательно нельзя получить
      указатель на конструктор.
      Но эти ограничения можно обойти, если определить функцию,
      содержащую вызов конструктора и возвращающую построенный объект.
      Это удачно, поскольку нередко бывает нужно создать новый объект,
      не зная его истинного типа. Например, при трансляции иногда
      возникает необходимость сделать копию дерева, представляющего
      разбираемое выражение. В дереве могут быть узлы выражений разных
      видов. Допустим, что узлы, которые содержат повторяющиеся в выражении
      операции, нужно копировать только один раз. Тогда нам потребуется
      виртуальная функция размножения для узла выражения.
      Как правило "виртуальные конструкторы" являются стандартными
      конструкторами без параметров или конструкторами копирования

(c) Бьерн Страустурп.
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #5 : 07-09-2008 20:18 » 

dimka, я имел ввиду что нет смысла их деражать как стандартные функции. По крайней мере для меня.
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Лёха
Гость
« Ответ #6 : 08-09-2008 04:49 » 

      Конструктор не может быть виртуальным, поскольку для правильного
      построения объекта он должен знать его истинный тип.
      Вот и строил бы конструктор НЕ правильно объект, не будучи виртуальным ... или строил бы не знаючи его истиный тип )
« Последнее редактирование: 08-09-2008 05:16 от Вад » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 08-09-2008 05:01 » 

Цитата: Лёха
или строил бы не знаючи его истиный тип )
Если бы, да кабы... В C++ это не так по объяснённым выше причинам, поэтому и обсуждать тут нечего.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Лёха
Гость
« Ответ #8 : 08-09-2008 07:01 » 

интересно девки пляшут
Записан
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #9 : 08-09-2008 07:06 » 

Цитата: Лёха
... или строил бы не знаючи его истиный тип )

так нельзя!

можно и нужно так
Код:
class expr {
      // ...
      public:
      expr(); // стандартный конструктор
      virtual expr* new_expr() { return new expr(); } //не стандартный конструктор
      };

      Виртуальная функция new_expr() просто возвращает стандартно
      инициализированный объект типа expr, размещенный в свободной памяти.
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 08-09-2008 07:11 » 

Зайдём с другой стороны Улыбаюсь

Код:
class A 
{
public:
    A(){}
}

class B
: public A
{
public:
    B();
}

class C
: public A
{
public:
    C();
}

и как прикажешь компилятору понимать, что создавать в конструкции
Код:
A var;
A* pVar = new A();
если у тебя конструктор "виртуальный"? A, B, или, может, C? Будет создаваться A. И точка. Ибо компилятор телепатическими способностями не наделён Улыбаюсь
Записан
sss
Специалист

ru
Offline Offline

« Ответ #11 : 08-09-2008 08:03 » 

Блин, тема нонсенс для типизированных языков.
Записан

while (8==8)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 08-09-2008 09:02 » 

Цитата
и как прикажешь компилятору понимать, что создавать в конструкции
Код:

A var;
A* pVar = new A();
не, пример неубедительный Улыбаюсь Будет создаваться A , даже если "конструктор виртуальный"
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 08-09-2008 09:46 » 

Цитата: sss
Блин, тема нонсенс для типизированных языков.
Почему это? Для типизированного Object Pascal совсем не "нонсенс", но "нонсенс" для нетипизированного JavaScript.

Цитата: Вад
Будет создаваться A.
Цитата: Алексей1153++
Будет создаваться A , даже если "конструктор виртуальный"
В метафизическом смысле B и C - это тоже A. Поэтому, хотя вы и правы, но это ничего не объясняет Улыбаюсь А как тут сказать коротко, но ёмко, я ещё не придумал. Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #14 : 08-09-2008 12:06 » 

Лёха, Компилятор С++ долго не думает. Если есть двойственность построения участка кода, он просто отсылает "привет" в консоль. Чтобы программист сам определился, чего он хочет. При этом этот участок пропускается и объектный файл не строится. По названным dimka причинам, громоздить виртуальные конструкторы в С++ не имеет смысла. При написании кода, ты явно знаеш, какой именно класс будет использоваться, и соответственно его создаеш.
В С++ есть недочеты и сложности. Но это не один из них.
« Последнее редактирование: 08-09-2008 12:13 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #15 : 08-09-2008 13:45 » 

"Ну я на вас просто удивляюсь" (с)

Все согласны, что тема не имеет смысла, но продолжаете обсуждать. Блин, мне бы столько времени.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
sss
Специалист

ru
Offline Offline

« Ответ #16 : 09-09-2008 00:56 » 

dimka, что это за виртуальный конструктор в Object Pascal? Он виртуален только тем, что может указывать цепь конструкторов?
Код:
  type A = class
    constructor LoadFrom( filename: String); virtual;
  end;

  type B = class ( A)
    constructor LoadFrom( filename: String); virtual;
  end;

  class A
  {
     A( char* filename);
  }

  class B : A
  {
     B( char* filename) : A( filename) {};  // <= Виртуальный как в ObjectPascal ???
  }

Какая вообще виртуальность в JavaScript? Может быть не виртуальность, а использование VARIANT?

Записан

while (8==8)
zubr
Гость
« Ответ #17 : 09-09-2008 04:44 » 

Хмм... В ObjectPascal виртуальный конструктор также бессмыслен. Насколько я помню теорию, таблица виртуальных методов в ObjectPascal создается в конструкторе, поэтому бессмысленно делать конструктор виртуальным. Кстати код:
Цитата
Код: (Object Pascal)

...
type
  TX = class
     ...
  end;
  TY = class(TX)
     ...
  end;
var
   PX: ^TX; { объявление указателя типа TX  }
   Y: TY; { объявление переменной типа TY и создание объекта типа TY до начала выполнения кода }
begin
   PX := @Y;
   PX^.Сreate; { вызов конструктора объекта для инициализации начальными значениями }
...
не прокатит, будет аксесс виолейшн, так как объект Y не инициализирован. Тогда надо будет вызывать конструктор Y:
Код:
PX := @Y;
Y:=TY.Create;// или Y:=TX.Create;
PX^.Сreate;
Но тогда пропадает смысл виртуального конструктора.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #18 : 09-09-2008 05:26 » 

zubr, в CBuilder ( не уверен за VC) в конструкторе вообще нельзя вызывать виртуальные методы

Код:
  class A
  {
     A() { func();};
    virtual void func() { printf( "A::func");};
  }

  class B : A
  {
     B():A(){ };
    virtual void func() { printf( "B::func");};
  }

  void main()
  {
     B b;
  }

Напечатает A::func. Отсюда можно сделать вывод, что перезапись таблицы на очередном уровне полиморфизма производится перед вызовом конструктора текущего в иерархии потомка.
Возможно, и скорее всего, слово virtual для конструкторов в ObjectPascal указывает компилятору, что конструктор должен быть вызван после полного заполнения VTM на всех уровнях иерархии.
Записан

while (8==8)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 09-09-2008 07:06 » 

Цитата: sss
что это за виртуальный конструктор в Object Pascal? Он виртуален только тем, что может указывать цепь конструкторов?
Нет.

Цитата: zubr
не прокатит, будет аксесс виолейшн, так как объект Y не инициализирован.
Вполне возможно, мне не на чем проверить.

Цитата: zubr
Насколько я помню теорию, таблица виртуальных методов в ObjectPascal создается в конструкторе, поэтому бессмысленно делать конструктор виртуальным.
Тем не менее, они есть.

Здесь приводится пример использования виртуальных конструкторов через метакласс в Object Pascal.
http://www.rsdn.ru/article/Delphi/delphiabs.xml
Здесь конкретный класс передаётся как экземпляр метакласса и определяется не во время компиляции, а во время исполнения, и вызов конструктора объекта есть вызов виртуального метода у экземпляра метакласса, коим этот конструктор и является. Моё объяснение выше про разделение времени создания и инициализации объекта было неправильным.

На самом деле, если бы в Object Pascal существовал бы более внятный механизм reflections, то писать "virtual" у конструктора не пришлось бы. Здесь же получается, что метаклассы упорядочены в такую же иерархию, как и их классы - только в этом смысле оправдана виртуальность конструктора.

Цитата: sss
Какая вообще виртуальность в JavaScript?
Выражение "виртуальный метод" имеет смысл лишь в ряде языков, например, в C++. Но наличие таких методов означает включение полиморфизма поведения объекта во время исполнения. В таких языках, как JavaScript, полиморфизм поведения объектов существует всегда и не отключается, поэтому выражение "виртуальный метод" для таких языков большого смысла не имеет. Но, поскольку мы тут общаемся на территории C++-ников, то не вижу ничего плохого в том, чтобы, для большей им понятности, говорить про "виртуальные методы" в том числе и в JavaScript, полагая, что в JavaScript все методы всегда "виртуальны".

И вообще я про "виртуальность" в JavaScript не говорил, я говорил о том, что "виртуальные конструкторы" в JavaScript не могут существовать на уровне синтаксиса этого языка, поскольку моменты создания и инициализации объекта неразделимы.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #20 : 09-09-2008 07:11 » 

Цитата: sss
в CBuilder ( не уверен за VC) в конструкторе вообще нельзя вызывать виртуальные методы
Насколько я понимаю, применительно к C++ из конструктора вызов виртуальных методов бессмысленен, поскольку конструктор предка выполняется ещё до выполнения конструктора потомка, и в момент работы конструктора предка виртуальные методы потомка просто ещё не определены. Хотя, быть может, это и не так - иначе будут проблемы с абстрактными методами. Но если это не так, то будут проблемы при работе самих виртуальных методов, поскольку они относятся к коду потомка, а объект как объект класса потомка ещё не определён - атрибуты потомка ещё не инициализированы.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
sss
Специалист

ru
Offline Offline

« Ответ #21 : 09-09-2008 07:23 » 

dimka, так зачем тогда слово virtual в ObjectPascal для constructor? Зачем было вообще в тему ANSI С++ замешивать ObjectPascal, который до компиляции выполняет над иерархиями классов дополнительную, работу  "являющуюся деталью реализации, скрытой от программиста"?

Квадратура круга forever..
« Последнее редактирование: 09-09-2008 07:25 от sss » Записан

while (8==8)
Лёха
Гость
« Ответ #22 : 09-09-2008 07:33 » 

McZim привел хороший пример
Код:
class expr {
      // ...
      public:
      expr(); // стандартный конструктор
      virtual expr* new_expr() { return new expr(); } //не стандартный конструктор
      };

       Сдесь на этапе компиляции не известно объект какого типа будет создаваться. Возможно я хотел что бы именно виртуальный конструктор заменял примеры подобного рода.
Товарищи ... кинте ссыллок, кто сколько сможет ) на статьи по поводу виртуальных функций, VTBL, хочеццо  подробнее узнать про тайну третьей планеты )
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 09-09-2008 07:49 » 

Цитата
Сдесь на этапе компиляции не известно объект какого типа будет создаваться
expr и будет создаваться )
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 09-09-2008 08:12 » 

Цитата: sss
Зачем было вообще в тему ANSI С++ замешивать ObjectPascal, который до компиляции выполняет над иерархиями классов дополнительную, работу  "являющуюся деталью реализации, скрытой от программиста"?
Для общего развития. Автор темы заявил, что пытается понять, почему конструктор не может быть виртуальным. И ему тут объясняют, почему не может именно в C++ - для этого нужен Object Pascal Ага.

И о какой же "скрытой от программиста" реализации идёт речь, если программист явно программирует эту "дополнительную работу над иерархиями классов"?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
sss
Специалист

ru
Offline Offline

« Ответ #25 : 09-09-2008 08:39 » 

Так это же цитата из статьи http://www.rsdn.ru/article/Delphi/delphiabs.xml  Ага
Записан

while (8==8)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #26 : 09-09-2008 13:02 » 

sss, и что? Статья - не откровение. Не надо литературные приёмы автора буквально принимать на веру. Улыбаюсь А вот в виртуальные конструкторы верить не нужно - нужно лишь проверить в Delphi или Free Pascal Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #27 : 09-09-2008 13:33 » 

Цитата
Сдесь на этапе компиляции не известно объект какого типа будет создаваться
expr и будет создаваться )
Метод виртуальный - в классе-потомке может быть создан другой объект. Правильнее сказать, что вызывающая метод программа не может знать, указатель на объект какого типа вернется (но точно известно, что или expr, или его потомки).
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline Offline

« Ответ #28 : 10-09-2008 01:38 » 

dimka, так что же все таки обозначает virtual constructor в ObjectPascal? Интересно. Я как раз не только не верю в виртуальные конструкторы, но и вообще все время пытаюсь доказать об несуществующем термине. Я так понимаю: в ObjectPascal вызов виртуального конструктора вначале выделяет память под объект класса, заполняет всю связанную с классом информацию (RTTI, VTM), а затем просто вызывает метод, обрамленный в определении класса как virtual constructor.
Записан

while (8==8)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #29 : 10-09-2008 03:39 » 

Цитата: sss
Я как раз не только не верю в виртуальные конструкторы, но и вообще все время пытаюсь доказать об несуществующем термине.
Вот доказывать несуществование термина, когда термин употребляется в Object Pascal и в шаблонах проектирования - занятие бессмысленное. Нужно разобраться в том, какой смысл вкладывают авторы в этот термин.

Тут нечего доказывать, но можно спорить с авторами о том, что они выбрали неудачный термин.

Это уже несколько выходит за рамки раздела о C++ и подходит для раздела о Delphi, но всё же:
Цитата: sss
Я так понимаю: в ObjectPascal вызов виртуального конструктора вначале выделяет память под объект класса, заполняет всю связанную с классом информацию (RTTI, VTM), а затем просто вызывает метод, обрамленный в определении класса как virtual constructor.
Ты понимаешь, что такое метакласс? Для чего появились метаклассы сперва в Smalltalk, а потом расползлись по другим языкам?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #30 : 10-09-2008 06:24 » 

мда, очень прикольно получается. Говорим о том что, существование виртуального конструктора это бессмыслица, но и говорить о том что его не существует, тоже бессмыслица Улыбаюсь
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
zubr
Гость
« Ответ #31 : 10-09-2008 07:00 » 

sss, дело в том, что в Delphi (в отличие от C++) в конструкторе класса-наследника конструктор родительского класса автоматически не вызывается, его можно вызывать (а можно не вызывать, правда последствия могут быть разными) с помощью ключевого слова inherited. То есть конструктор родительского класса вызывается как обычный метод, отсюда - почему бы ему не быть виртуальным?
Записан
sss
Специалист

ru
Offline Offline

« Ответ #32 : 10-09-2008 07:44 » 

Цитата
Ты понимаешь, что такое метакласс? Для чего появились метаклассы сперва в Smalltalk, а потом расползлись по другим языкам?

Дак объясни наконец что такое матакласс. Никогда не пользовался. Два раза спрашивал - что значит virtual constructor?

zubr, ни фига подобного... Или фига подобного? Может именно когда virtual constructor такое поведение?
« Последнее редактирование: 10-09-2008 07:47 от sss » Записан

while (8==8)
zubr
Гость
« Ответ #33 : 10-09-2008 08:51 » 

Цитата
zubr, ни фига подобного... Или фига подобного? Может именно когда virtual constructor такое поведение?
Код:
TA = class
  private
  public
    constructor Create;
  end;

  TB = class(TA)
  public
    constructor Create;
  end;


constructor TA.Create;
begin
 MessageBox(0, 'A', '', MB_OK);
end;

constructor TB.Create;
begin
 inherited Create;
 MessageBox(0, 'B', '', MB_OK);
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  b:TB;
begin
 b:=TB.Create;
end;
При нажатии на Button1 выскакивает сначала A затем B. Если конструктор TB  сделать без inherited то только В. Все тоже самое если объявить:
Код:
TA = class
  private
  public
    constructor Create; virtual;
  end;

  TB = class(TA)
  public
    constructor Create; override;
  end;
Записан
sss
Специалист

ru
Offline Offline

« Ответ #34 : 10-09-2008 09:07 » 

А как инициализированы члены класса? Зарезервированным словом default? А конструкторы классов членов вызываются?

Все сдаюсь... Надоело говорить про Delphi в теме об ANSI C++. Только не знаю, что признать то? Суверенитет ObjectPascal???
Записан

while (8==8)
zubr
Гость
« Ответ #35 : 10-09-2008 09:34 » 

Цитата
А как инициализированы члены класса? Зарезервированным словом default? А конструкторы классов членов вызываются?
Если не вызовешь конструктор родителя, то никак... А черт его знает...
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #36 : 10-09-2008 11:09 » 

Цитата: sss
Дак объясни наконец что такое матакласс. Никогда не пользовался.
Как известно, в типизированных языках объекты называют другими словами экземплярами классов. Метакласс - это класс классов, по отношению к которому уже классы являются экземплярами метакласса. Так сказать, класс второго порядка.

Например, в Java есть класс Class, который, как и всякий класс, является потомком класса Object, но класс Class есть такой класс, экземплярами которого являются все прочие классы (в том числе и Object, и даже сам класс Class) - т.е. класс Class фактически является метаклассом, хотя формально он тоже класс (тип данных) в языке.

Тоже самое в языках .NET: есть класс Type, экземпляры которого описывают другие классы (и могут описывать самого себя) - т.е. класс Type фактически является метаклассом, хотя формально является классом. Объекты типа Type играют важную роль в механизме reflections, при использовании которого код программы можно обрабатывать (другим кодом) как данные.

Для чего это нужно? Для того, чтобы была возможность передать информацию о типе во время исполнения как данные. В этом случае класс рассматривается не как синтаксическая конструкция времени программирования и компиляции, а как данные (экземпляр метакласса) времени исполнения со всеми нужными свойствами (в частности, ссылкой на конструктор, возможно, коллекциями ссылок на методы, свойства и т.д., перечнем реализуемых интерфейсов, ссылкой на класс-предок и т.д. - зависит от конкретного языка программирования).

Пример из .NET, аналогичный примеру из Delphi, будет таким:
Код: (Text)
using System;
using System.Reflection;

namespace Program
{
    class Program
    {
        class A
        {
            public A()
            {
                Console.WriteLine("A");
            }
        }

        class B: A
        {
            public B()
            {
                Console.WriteLine("B");
            }
        }

        static A CreateA(Type type)
        {
            // Извлекаем из описания класса информацию о его конструкторе.
            // Выбираем из всех конструкторов по их сигнатурам конструктор без параметров -
            // конструктор по умолчанию.
            Type[] constructorArgumentsTypes = new Type[0];
            ConstructorInfo constructor = type.GetConstructor(constructorArgumentsTypes);
               
            // Вызываем конструктор по умолчанию неизвестного класса и получаем объект этого
            // неизвестного класса.
            object[] constructorArguments = new object[0];
            object instance = constructor.Invoke(constructorArguments);

            // Пытаемся привести объект неизвестного класса к классу A, если неудачно, то возвращаем null.
            return instance as A;
        }

        static void Main(string[] args)
        {
            A a;

            a = CreateA(typeof(A));
            Console.ReadLine();

            a = CreateA(typeof(B));
            Console.ReadLine();
        }
    }
}

В результате получаем:

Код: (Text) Вывод программы
A

A
B

Если отказаться от приведения к A, то таким образом можно создать любой объект любого типа, но "виртуальности" конструкторов в явном виде здесь нет, в отличие от Object Pascal.

В Object Pascal конструктор нужно объявлять "виртуальным" по всей видимости лишь для того, чтобы указатель на него попал в таблицу виртуальных методов, а эта таблица используется как данные в экземпляре метакласса.

Для чего вообще передавать информацию о классах как данные? Это вопрос философский Улыбаюсь Лично я пользовался reflections только пару раз в качестве "противопожарного" средства - заплатки, когда нужно было сделать быстроее решение, а времени на перепроектирование иерархии классов не было. Может быть полезно, когда в чужой dll-ке без исходного кода определены типы, которые нельзя уже переделать, встроить в свою иерархию классов, но очень хочется - тогда можно взять reflections Улыбаюсь

Цитата: Алексей1153++
чтоб не трудно было про оба языка сразу говорить
"Оба" - это ты оптимист. Всё ещё только начинается Улыбаюсь
« Последнее редактирование: 10-09-2008 11:13 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #37 : 10-09-2008 11:30 » 

а я оптимист, базару нету ))
Записан

Лёха
Гость
« Ответ #38 : 12-09-2008 07:33 » 

Цитата
Сдесь на этапе компиляции не известно объект какого типа будет создаваться
expr и будет создаваться )

Ты слишком придераешся к моим словам ... ну это ладно ... 
Возможно я отступаю от темы, но всётаки кинте ссылок на тему виртуальных функций, возможно это даст мне ответы на кое какие вопросы, Спасибо.
Записан
McZim
Команда клуба

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #39 : 12-09-2008 07:39 » 

Лёха, наздоровье.

http://lib.ru/CPPHB/cpptut.txt_with-big-pictures.html
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #40 : 12-09-2008 13:49 » 

Finch'у +1, просто супер, коротко и четко... и добавить нечего.

Лёха,
Цитата
Сдесь на этапе компиляции не известно объект какого типа будет создаваться
expr и будет создаваться )
Совершенно верно пишет пушистый, тут точно известно, что будет создаваться.

RXL,
Цитата
Сдесь на этапе компиляции не известно объект какого типа будет создаваться
expr и будет создаваться )
Метод виртуальный - в классе-потомке может быть создан другой объект. Правильнее сказать, что вызывающая метод программа не может знать, указатель на объект какого типа вернется (но точно известно, что или expr, или его потомки).
в потомке не может быть создан другой объект, не важно виртуальна ли функция или нет, как уже было сказано таблица создается/обновляется (что точно делается это личное дело компилятора) после того как отработал конструктор базового класса, поэтому отработает ровно, то что написано.
Записан

С уважением Lapulya
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #41 : 12-09-2008 15:21 » 

lapulya, опять у нас недопонимание... Ответь, пожалуйста, развернуто.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #42 : 12-09-2008 16:17 » 

Цитата: lapulya
в потомке не может быть создан другой объект, не важно виртуальна ли функция или нет, как уже было сказано таблица создается/обновляется (что точно делается это личное дело компилятора) после того как отработал конструктор базового класса, поэтому отработает ровно, то что написано.
В том примере виртуальный метод new_expr не вызывался из конструктора expr, поэтому твоё замечание в такой формулировке (привязка к порядку вызова конструкторов) бессмысленно.

Другое дело, что для создания экземпляра конкретного класса нужно иметь конкретную же фабрику, поэтому тот пример вопрос про создание произвольного объекта не решает сам по себе, а лишь позволяет вынести выбор конкретного класса создаваемого экземпляра в другую часть системы, которая на основании каких-либо данных выберет, какую конкретную фабрику создать.

Или, другими словами, фабрика (как шаблон проектирования) позволяет разделить во времени момент (и в пространстве кода место) выбора типа создаваемых объектов и момент (и место в коде) создания самих объектов.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Лёха
Гость
« Ответ #43 : 13-09-2008 11:10 » 


это ведь второе издание Страуструпа, у мну оно уже есть Жаль
там не много инфы по поводу vtbl
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #44 : 18-09-2008 15:24 » 

RXL, Сорри, я был не внимателен (с чего то придумал себе, что функция из конструктора вызывается)... все верно. И точно димка подметил, что это как правило (но далеко не всегда и на эту тебу есть и шаблон проектирования, хотя я им никогда не пользовался) выносится из класса в фабрику.
« Последнее редактирование: 18-09-2008 15:26 от lapulya » Записан

С уважением Lapulya
Страниц: 1 2 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines