Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Виртуальный конструктор, Visual C++ 
:(
    Опции темы
valex13
Дата 8.6.2003, 04:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 29.1.2003
Где: Иркук. область, г . Иркутск

Репутация: нет
Всего: 1



Господа! Как сделать линейку объектов конструкторы бы которых запускались не с низу в верх ( от предка к потомкам ), а наоборот. Например если делать виртуальный метод, то происходит именно так.
PM MAIL ICQ   Вверх
RAN
Дата 8.6.2003, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Экс. модератор
Сообщений: 709
Регистрация: 14.3.2003
Где: Щёлково Моск.обл.

Репутация: 5
Всего: 6



Цитата
Например если делать виртуальный метод, то происходит именно так.

Я чего-то не понял, что это значит.

А по поводу конструкторов, мне вот что интересно: нельзя ли явно вызывать конструктор предка в конструторе потомка (сам не пробывал, компилятора под рукой нет)

Код

class A
{
/* всякая всячина */
public:
       A(); // конструтор предка
};

class B : public A
{
...............
public:
       B(); //конструтор потомка
};

A::A()
{
/*инициализируем класс A */
}

B::B()
{
/*инициализация B */
   A(); //Конструктор класса A
}


PM MAIL ICQ   Вверх
vickr
Дата 8.6.2003, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 13.5.2003
Где: Санкт-Петербург

Репутация: нет
Всего: нет



To RAN
Да, но более привычный синтаксис (по крайней мере, именно так - можно):
Код

B::B():A()
{
/*инициализация B */

}

--------------------
Каждую секунду, тыкая в клавиши, мы давим насмерть не менее 1000 микробов =:)
PM MAIL   Вверх
RAN
Дата 9.6.2003, 07:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Экс. модератор
Сообщений: 709
Регистрация: 14.3.2003
Где: Щёлково Моск.обл.

Репутация: 5
Всего: 6



vickr, по-моему ты не понял. Твой синтаксис запустит сначала конструктор A, а затем B. Надо то наоборот. Как?
PM MAIL ICQ   Вверх
Vyacheslav
Дата 9.6.2003, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



В С++ виртуальных конструкторов не существует. Так же нельзя поменять порядок вызова конструкторов предков. Это данность языка и с этим ничего поделать нельзя. Исключением их правила являются виртуальные конструкторы VCL-библиотеки, но "тяжкое наследие" Object Pascal.
Что же касается самой необходимости его применения, скажи что ты хочешь и я скажу (может быть) что делать.
Да, и еще одно: виртуальные методы предназначены не для изменения порядка вызова, а для поддержки полиморфизма.


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
valex13
Дата 9.6.2003, 09:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 29.1.2003
Где: Иркук. область, г . Иркутск

Репутация: нет
Всего: 1



Я использую их пока для изменения порядка вызова. Например метод GetData для нового обьекта ( потомка ) будет вперед запущен, а потом ( если я укажу в методе ) вызову метод предка.
У меня в конструкторе предка стоит загрузка конкретной DLL и вся работа завязана на ее "хендле". Получается если я создам новый обьект и мне зохочеться указать название DLL другое, то облом? Не хочеться мне заводить еще одну загрузку DLL (Динамическую). А если даже и загрузить, то тогда что делать со старой?
PM MAIL ICQ   Вверх
DENNN
Дата 9.6.2003, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 3878
Регистрация: 27.3.2002
Где: Москва

Репутация: 1
Всего: 43



если оформить так?
Код

int B::GetData()
{
....////выполняем необходимые дейсвия
return A::GetData();
}

PM ICQ   Вверх
valex13
Дата 9.6.2003, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 29.1.2003
Где: Иркук. область, г . Иркутск

Репутация: нет
Всего: 1



Для метода GetData я так и делаю, а вот DENN как быть с конструктором?
Я бы хотел подключаться в другой DLL
PM MAIL ICQ   Вверх
DENNN
Дата 9.6.2003, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 3878
Регистрация: 27.3.2002
Где: Москва

Репутация: 1
Всего: 43



В твоем случае, можно переписать объявление конструктора так:
Код

class A
{
public:
A(char* LibraryName = "MyPreviousDLL")//по умолчанию загружается твоя основная
{
LoadLibrary(LibraryName);
.......
}
}
class B : public A
{

}

//сам код
A var1;
B var2("MyNewDll.dll");

Конечно метод не универсальный, но в твоем случае исправлений в коде почти не требуется.
Можно предложить и другие "хитрые способы", но суть не измениться - C++ нельзя изменить порядок вызова базовых кострукторов (это основа механизма наследования).
PM ICQ   Вверх
Fantasist
Дата 9.6.2003, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Цитата
Я использую их пока для изменения порядка вызова.



Для этого виртуальные методы не нужны совершенно. Способ предложенный DENN отлично используется и для не виртуальных методов.


--------------------
Волны гасят ветер...
PM MAIL   Вверх
valex13
Дата 10.6.2003, 05:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 29.1.2003
Где: Иркук. область, г . Иркутск

Репутация: нет
Всего: 1



Что касается конструктора DENN, ты абсолютно прав. Я так и сделаю Признаюсь, у меня была схожая мысль. Что-ж. Я ранее ( до того как задать вопрос ) делал так:
class A
{
public A()
{
LoadLibrary(LibraryName);
}
public A( newNameLibr) {LibraryName = newNameLibr; A();}

}
Таким образом:
B var ("MyName");
А как быть, если у меня наследник в третьем колене?
Есть A
Есть B::A с простым конструктором
и Есть С::B::A

Что же касается виртуальных методов, то если не сделаешь в потомке метод виртуальным, то при вызове B::GetData вызовиться GetData предка. Даже если он переопределен. Или я ошибаюсь....

PM MAIL ICQ   Вверх
RAN
Дата 10.6.2003, 07:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Экс. модератор
Сообщений: 709
Регистрация: 14.3.2003
Где: Щёлково Моск.обл.

Репутация: 5
Всего: 6



Цитата
Что же касается виртуальных методов, то если не сделаешь в потомке метод виртуальным, то при вызове B::GetData вызовиться GetData предка. Даже если он переопределен. Или я ошибаюсь....

Чепуха, достаточно только в классе предке поставить virtual и класс потомок сможет его перегружать. Там писать virtual все не обязательно, но я всегда пишу, чтоб было наглядно видно - метод перегружен, но это дело вкуса.
Кстати, если бы даже метод не был виртуальным, то B::GetData() не мог бы всё равно вызывать метод предка A::GetData(), он бы вызывал свой метод. Так часто бывает с переменными, когда в двух классах, предке и потомке, одноимённые переменные, каждый будет видеть свою.
Смысл виртуальных методов не только в том, что ты можешь заменить функцию класса-предка на новую (именно заменить, а не вызвать раньше), но и в том, что даже если ты преобразуешь объект класса потомка к классу предка, тот всё равно будет видеть функцию класса потомка. Полиморфизм, батенька - методы, реально, принадлежат не классу, а объекту, созданному на его основе :
Код

class A {
public: virtual int GetData() { return 1; }
};

class B : public A{
public:
virtual int GetData() { return 2; }
int GetData2() { return 3; }
};

в программе:
A *class1;
B *class2;
class2 = new B;
int x = class2->GetData(); //вызовет B::GetData() и вернёт 2
class1 = class2;
x = class1->GetData(); //опять вызовет B::GetData() и вернёт 2
x = class1->GetData2(); //ОШИБКА, A::GetData2 не существует


PM MAIL ICQ   Вверх
Vyacheslav
Дата 10.6.2003, 09:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



Цитата(valex13 @ 10.6.2003, 05:33)
Что же касается виртуальных методов, то если не сделаешь в потомке метод виртуальным, то при вызове B::GetData вызовиться GetData предка. Даже если он переопределен. Или я ошибаюсь....

Ошибаешься.
Переопредеялять можно и невиртуальные методы. Вся разница в работе виртуальных и невиртуальных методов начинает проявляться, когда задействуешь полиморфизм
Код

class A
{
public
  void func() {  cout << "funcA" << endl; }
  virtual void vfunc { cout << "vfuncA" <<endl; }
};
class B :public A
{
public
  void func() {  cout << "funcB" << endl; }
  virtual void vfunc { cout << "vfuncB" <<endl; }
}

A a;
B b;

a.func();
b.func();

a.vfunc();
b.vfunc();

A* pa = (A*)&b;
//здесь проявляется различие между виртуальным и невиртуальным методом
pa->func();
pa->vfunc();


результат паботы программы
Код

funcA
funcB
vfuncA
vfuncB
funcA
vfuncB



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
valex13
Дата 11.6.2003, 08:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 29.1.2003
Где: Иркук. область, г . Иркутск

Репутация: нет
Всего: 1



А если вот такая ситуация:
Есть А и наследник В
Оба имеют один и тот же виртуальный метод OnCalc
Делаю так:
A *ab = new A();
B *bb = (A*)ab;
bb->OnCalc();
и вызывается OnCalc() объекта A.
А мне необходимо, чтобы вызывался метод объекта A?

Это сообщение отредактировал(а) valex13 - 11.6.2003, 08:12
PM MAIL ICQ   Вверх
valex13
Дата 11.6.2003, 08:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 29.1.2003
Где: Иркук. область, г . Иркутск

Репутация: нет
Всего: 1



Извините
bb->OnCalc(); - это описка.
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0648 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.