Форум программистов, компьютерный форум CyberForum.ru

Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 35, средняя оценка - 4.66
kravam
быдлокодер
 Аватар для kravam
1513 / 873 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
02.06.2011, 21:48     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #1
Ну то есть так: есть родительский и дочерний класс, в родительском определен виртуальная функция и вызывается в его конструкторе (камень преткновения; и не вызывать нельзя). А есть дочерний класс и в нём эта вирутальная функция переопределена. Я создаю объект дочернего класса, он благополучно вызывает конструктор родительского класса и вызывается эта функция, но РОДИТЕЛЬСКИЙ вариант. А мне нужен ДОЧЕРНИЙ. Спасибо кто поможет. Может я где теорию упустил, не знаю.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
 
 
 
//Это вот базовый класс
                         //++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class base{
 public:
 
  //А вот в этом конструкторе и будет вызываться виртуальная функция
  base ();         
 
  //Вот эту фунцию я сделал виртуальной
  virtual void f (){cout<< "Вот её текст, его я видеть не хочу!"<< endl;};
 //Это просто деструктор
  ~base () {}         
};
 
base::base () {
 f();
}         
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                         //++++++++++++++++++
 
 
//А это вот доченрний класс
                         //++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class sin: public base {
 public:
  sin ():base(){};
  ~sin () {};
 
  //Вот виртуальная функция, которую я переопределяю и которую очень хочется вызвать в конструкторе 
  //этого класса
  void f () ;
};
 
 
void sin::f () {
 cout<< "Вот этот текст я хочу увидеть, но не получается"<< endl;
};
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                         //++++++++++++++++++
 
 
 
int main() {
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
 sin k;
 getchar ();
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.06.2011, 21:48     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса?
Посмотрите здесь:

В конструкторе вложенного класса инициализируется приватное поле. Потом вызывается функция-метод этого класса и выводит значение этого поля НО НЕ ТО! C++
как в конструкторе класса передать параметром указатель на функцию? C++
ООП в C++: Вызов родительского конструктора с параметром при создании объекта дочернего класса C++
C++ Как вызвать метод родительского класса;
Как вызвать функцию родительского класса? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
tapka
3 / 3 / 1
Регистрация: 05.12.2009
Сообщений: 13
03.06.2011, 00:00     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #2
Попробуй обратиться к объекту производного класса через указатель
C++
1
2
sin *k;
k = new sin();
kravam
быдлокодер
 Аватар для kravam
1513 / 873 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
03.06.2011, 01:20  [ТС]     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #3
Не помогает, просто создаётся объект типа sin, соответственно вызывается конструктор родительского объекта, и f (), определённая в родительском же объекте. А мне надо чтобы та функция вызывалась, что переопределена в дочернем объекте.

Добавлено через 13 минут
Решилось так: в конструктор дочернего класса я вставил вызов функции f, а из конструктора базового класса этот конструктор убрал.
C++
1
2
3
4
5
6
7
base::base () {
 //f();
}         
//....................................
  sin ():base(){
   f ();
  };
Решилось? Нет. Дело в том, что если я для каждого дочернего класса буду определять алгоритм вызова f (), какой смысл в базовом классе? Он не нужен. Тогда уж проще сразу объявить два или сколько-то там дочерних классов, каждыйкак САМОМСТОЯТЕЛЬНУЮ сущность и в конструкторе каждого прописать подобный вызов.
C++
1
2
3
4
5
6
7
  sin_0 ():base(){
   f ();
  };
//.....................................
  sin_1 ():base(){
   f ();
  };
Только мне непонятно тогда, в чём прикол ООП, если я не могу воспользоваться элементарщиной- полиморфизмом? Убирать тогда родительско-дочернюю концепцию и возвращаться на круги своя. Жаль. Очень хочу быть опровергнутым.
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
03.06.2011, 01:53     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #4
понял - ты хочешь вызывать из базового класса какую то версию функции объявленной в нем но переопределенной в производном ..
но ведь базовый класс не знает ни о каких других версиях этой функции ( у него своя таблица vtable в которой только адреса функций базового) -> не ясно как ты хочешь добиться такого эффекта.

пс если получится отпишись
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 07:39     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #5
я так понял, что нужно в дочернем классе вызвать функцию родительского, которая была переопредела в нём. Если это так, то нужно просто явно указывать версию sin::f() - функция родительского класса, base::f() - функция дочернего. То есть наоборот блин. Тогда никаких неоднозначностей не будет

Добавлено через 4 часа 11 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class sin: public base {
 public:
  sin ():base(){ sin::f(); base::f();};
  ~sin () {};
 
  //Вот виртуальная функция, которую я переопределяю и которую очень хочется вызвать в конструкторе 
  //этого класса
  void f () ;
};
 
 
void sin::f () {
 cout<< "Вот этот текст я хочу увидеть, но не получается"<< endl;
};
здесь в конструкторе обе функции вызываются
no0ker
100 / 87 / 4
Регистрация: 17.12.2010
Сообщений: 416
03.06.2011, 08:28     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #6
kravam, при создании объекта производного класса, сначала вызывается конструктор базового класса (со своей функцией void f() ), а потом конструктор производного класса(опять же со своей функцией void f() ). то есть конструктор базового класса (вместе со своими функциями) вызывается всегда, а вы хотите, что бы он не вызывался что ли?
Mr.X
Эксперт С++
 Аватар для Mr.X
2798 / 1574 / 246
Регистрация: 03.05.2010
Сообщений: 3,651
03.06.2011, 08:32     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #7
Дело в том, что виртуальность функции проявляется не всегда, а только в том случае, когда она вызывается через ссылку или указатель на базовый класс. Во всех остальных случаях функция воспринимается компилятором как невиртуальная.
tapka
3 / 3 / 1
Регистрация: 05.12.2009
Сообщений: 13
03.06.2011, 13:22     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #8
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
кстати, если бы у виртуальной функции базового класса не было бы тела, наверняка появилась бы ошибка типа "access violation"
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 319
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
03.06.2011, 15:18     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #9
Цитата Сообщение от tapka Посмотреть сообщение
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
Я не специалист по Си++, но мне тоже кажется, что так оно и есть. Конструктор вызывается для инициализации собственных полей, а потому конструктор может вызывать только методы, определённые в данном классе (или у родителей). Логично, что работать с виртуальными методами можно только после того, как объект уже создан, а в процессе работы конструктора объект как бы ещё не до конца создан
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 15:25     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #10
внутри конструктора производного класса можно работать с методами базового класса и вызывать любые свои методы
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
03.06.2011, 16:40     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #11
Evg, по-моему первым делом создается таблица виртуальных ф-ций и VPTR (указатель на эту таблицу) инициализируется первым делом при входе в конструктор (на MSVS VPTR имеет смещение 0, относительно объекта), а значит в конструкторе уже можно использовать виртуальные ф-ции. Другое дело, что надеется на это не стоит, т.к. в стандарте это не прописанно, а значит не факт, что какой-нибудь компилятор не сделает по другому.
Но вот такой код работает (пришлось изменить имя класса с sin на sinn, иначе студия негодовала)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
 
 
 
//Это вот базовый класс
                         //++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class base{
 public:
 
  //А вот в этом конструкторе и будет вызываться виртуальная функция
  base ();         
 
  //Вот эту фунцию я сделал виртуальной
  virtual void f (){cout<< "Вот её текст, его я видеть не хочу!"<< endl;};
 //Это просто деструктор
  ~base () {}         
};
 
       
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                         //++++++++++++++++++
 
 
//А это вот доченрний класс
                         //++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class sinn: public base {
 public:
  sinn ():base(){};
  ~sinn () {};
 
  //Вот виртуальная функция, которую я переопределяю и которую очень хочется вызвать в конструкторе 
  //этого класса
  void f () ;
};
 
 base::base () {
 reinterpret_cast<sinn*>(this)->sinn::f();
}  
void sinn::f () {
 cout<< "Вот этот текст я хочу увидеть, но не получается"<< endl;
};
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                         //++++++++++++++++++
 
 
 
int main() {
 SetConsoleCP(1251);
 SetConsoleOutputCP(1251);
 sinn k;
 getchar ();
}
kravam, следует учесть, что это лютый быдлокод, и делать так, конечно же, не нужно)
pito211
 Аватар для pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 16:51     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #12
есть такая книга. Оформлена так, что главы там называются "советы" и в ней очень много написано как раз про то как работают все эти касты с наследоваными классами. Может кто вспомнит автора\название?
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 319
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
03.06.2011, 16:54     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #13
Цитата Сообщение от Kastaneda Посмотреть сообщение
Evg, по-моему первым делом создается таблица виртуальных ф-ций и VPTR
Я говорил не о том, как оно технически реализовано, а том, как оно идиологически должно быть устроено. При работе с виртуальными классами должна быть как минимум одна точка, где известен тип объекта - это его создание (ну и, соотвественно, конструктор). При этом базовый клас вообще ничего не должен знать о производных классах (ибо в противном случае это вообще не ООП, что имееет место быть в твоём примере из поста #11)
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
03.06.2011, 17:05     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #14
Цитата Сообщение от Evg Посмотреть сообщение
При этом базовый клас вообще ничего не должен знать о производных классах (ибо в противном случае это вообще не ООП, что имееет место быть в твоём примере из поста #11)
если без утопий, то например используется в паттерне шаблонный метод
Kastaneda
03.06.2011, 17:09
  #15

Не по теме:

Цитата Сообщение от Evg Посмотреть сообщение
ибо в противном случае это вообще не ООП, что имееет место быть в твоём примере из поста #11
Это да) Мы похоже о разных вещах говорим.
Логично, что работать с виртуальными методами можно только после того, как объект уже создан, а в процессе работы конструктора объект как бы ещё не до конца создан
Ты про логику, а я про реализацию, которая позволяет обойти логику. На то он и C++ )))

Mr.X
Эксперт С++
 Аватар для Mr.X
2798 / 1574 / 246
Регистрация: 03.05.2010
Сообщений: 3,651
03.06.2011, 17:09     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #16
Цитата Сообщение от Kastaneda Посмотреть сообщение
а значит в конструкторе уже можно использовать виртуальные ф-ции
На самом деле по стандарту виртуальныные функции, вызываемые в конструкторе или деструкторе, принадлежат к тому же классу, что и конструктор или деструктор. Если было бы иначе, то, как уже замечено выше, это было бы нарушением инкапсуляции.
kravam
быдлокодер
 Аватар для kravam
1513 / 873 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
03.06.2011, 17:18  [ТС]     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #17
Kastaneda, а Вы не могли бы пояснить, в Вашем коде мне худо-бедно понятно всё. Ну то есть создаётся производный класс (сперва базовый и указатель на него переопределяется в указатель на производный (который типа есть ну или вот-вот будет) и вызывается функция производного класса)
Это понятно. Но как может вызываться функция объекта, которого не то что нет, а и быть не может?

Напишем в вашем коде так:
C++
1
2
 //sinn k;
 base k;
То есть создадим объект ТОЛЬКО базового класса. И видим, что вызывается f() производного класса, которого даже нет в планах!

Как это понимать? Я вообще теряюсь.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16824 / 5245 / 319
Регистрация: 30.03.2009
Сообщений: 14,121
Записей в блоге: 26
03.06.2011, 17:19     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #18
Цитата Сообщение от Kastaneda Посмотреть сообщение
Ты про логику, а я про реализацию, которая позволяет обойти логику. На то он и C++ )))
Ну потому и получился быдлокод
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
03.06.2011, 17:33     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #19
Цитата Сообщение от kravam Посмотреть сообщение
Kastaneda, а Вы
Ты

Этот код просто для примера, в данном конкретном случае он работает, но, что будет, если создать объект базового класса - неизвестно (студия вывела сообщение из sin::f(), ибо темные силы движут ей))). Так делать вообще нельзя, о чем уже было написанно выше.

Добавлено через 5 минут

Не по теме:

студия вывела сообщение из sin::f()
начинаю видеть в этом логику... может позже дойдет...

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.06.2011, 17:58     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса?
Еще ссылки по теме:

C++ Как построить экземпляр дочернего класса на основе готового экземпляра базового класса?
Как убрать функцию из дочернего класса? C++
Может ли метод родительского класса обратиться к полю дочернего класса C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
03.06.2011, 17:58     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? #20
А если у нас много производных классов и для каждого нужно вызывать свою функцию?

Цитата Сообщение от Kastaneda Посмотреть сообщение
если создать объект базового класса - неизвестно (студия вывела сообщение из sin::f(), ибо темные силы движут ей)))
я не понял вообще как это происходит. (наверное потому что код не завязан на переменных а просто выводит сообщение поэтому и нет ошибок)

самое смешное что если заменить reinterpret_cast на менее брутальное static_cast всё равно работает
Yandex
Объявления
03.06.2011, 17:58     Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса?
Ответ Создать тему
Опции темы

Текущее время: 08:03. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru