Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/29: Рейтинг темы: голосов - 29, средняя оценка - 4.83
kravam
быдлокодер
1709 / 896 / 105
Регистрация: 04.06.2008
Сообщений: 5,542
1

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

02.06.2011, 21:48. Просмотров 5466. Ответов 19
Метки нет (Все метки)

Ну то есть так: есть родительский и дочерний класс, в родительском определен виртуальная функция и вызывается в его конструкторе (камень преткновения; и не вызывать нельзя). А есть дочерний класс и в нём эта вирутальная функция переопределена. Я создаю объект дочернего класса, он благополучно вызывает конструктор родительского класса и вызывается эта функция, но РОДИТЕЛЬСКИЙ вариант. А мне нужен ДОЧЕРНИЙ. Спасибо кто поможет. Может я где теорию упустил, не знаю.

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 ();
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.06.2011, 21:48
Ответы с готовыми решениями:

Как вызвать функцию родительского класса?
#include &lt;iostream&gt; using namespace std; class foo{ void somefunc();...

Может ли метод родительского класса обратиться к полю дочернего класса
Может ли метод родительского класса обратиться к полю дочернего класса?

В конструкторе вложенного класса инициализируется приватное поле. Потом вызывается функция-метод этого класса и выводит значение этого поля НО НЕ ТО!
Друзья! Почему так? #include &lt;windows.h&gt; #include &lt;iostream&gt; using namespace...

Как вызвать метод родительского класса;
Собственно вопрос; Есть класс a и b; Класс b унаследован от класса a; И как...

Почему вызывается перегрузка виртуальной функции из приватной секции дочернего класса?
Как вообще такое происходит class A { public: virtual void...

19
tapka
4 / 4 / 4
Регистрация: 05.12.2009
Сообщений: 13
03.06.2011, 00:00 2
Попробуй обратиться к объекту производного класса через указатель
C++
1
2
sin *k;
k = new sin();
0
kravam
быдлокодер
1709 / 896 / 105
Регистрация: 04.06.2008
Сообщений: 5,542
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 ();
  };
Только мне непонятно тогда, в чём прикол ООП, если я не могу воспользоваться элементарщиной- полиморфизмом? Убирать тогда родительско-дочернюю концепцию и возвращаться на круги своя. Жаль. Очень хочу быть опровергнутым.
0
OstapBender
584 / 523 / 75
Регистрация: 22.03.2011
Сообщений: 1,585
03.06.2011, 01:53 4
понял - ты хочешь вызывать из базового класса какую то версию функции объявленной в нем но переопределенной в производном ..
но ведь базовый класс не знает ни о каких других версиях этой функции ( у него своя таблица vtable в которой только адреса функций базового) -> не ясно как ты хочешь добиться такого эффекта.

пс если получится отпишись
0
pito211
186 / 173 / 18
Регистрация: 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;
};
здесь в конструкторе обе функции вызываются
1
no0ker
101 / 88 / 7
Регистрация: 17.12.2010
Сообщений: 416
03.06.2011, 08:28 6
kravam, при создании объекта производного класса, сначала вызывается конструктор базового класса (со своей функцией void f() ), а потом конструктор производного класса(опять же со своей функцией void f() ). то есть конструктор базового класса (вместе со своими функциями) вызывается всегда, а вы хотите, что бы он не вызывался что ли?
0
Mr.X
Эксперт С++
3182 / 1709 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
03.06.2011, 08:32 7
Дело в том, что виртуальность функции проявляется не всегда, а только в том случае, когда она вызывается через ссылку или указатель на базовый класс. Во всех остальных случаях функция воспринимается компилятором как невиртуальная.
0
tapka
4 / 4 / 4
Регистрация: 05.12.2009
Сообщений: 13
03.06.2011, 13:22 8
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
кстати, если бы у виртуальной функции базового класса не было бы тела, наверняка появилась бы ошибка типа "access violation"
0
Evg
Эксперт CАвтор FAQ
19303 / 7158 / 532
Регистрация: 30.03.2009
Сообщений: 20,034
Записей в блоге: 30
03.06.2011, 15:18 9
Цитата Сообщение от tapka Посмотреть сообщение
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
Я не специалист по Си++, но мне тоже кажется, что так оно и есть. Конструктор вызывается для инициализации собственных полей, а потому конструктор может вызывать только методы, определённые в данном классе (или у родителей). Логично, что работать с виртуальными методами можно только после того, как объект уже создан, а в процессе работы конструктора объект как бы ещё не до конца создан
0
pito211
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 15:25 10
внутри конструктора производного класса можно работать с методами базового класса и вызывать любые свои методы
0
Kastaneda
Jesus loves me
Эксперт С++
4942 / 3019 / 346
Регистрация: 12.12.2009
Сообщений: 7,622
Записей в блоге: 2
Завершенные тесты: 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, следует учесть, что это лютый быдлокод, и делать так, конечно же, не нужно)
1
pito211
186 / 173 / 18
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 16:51 12
есть такая книга. Оформлена так, что главы там называются "советы" и в ней очень много написано как раз про то как работают все эти касты с наследоваными классами. Может кто вспомнит автора\название?
0
Evg
Эксперт CАвтор FAQ
19303 / 7158 / 532
Регистрация: 30.03.2009
Сообщений: 20,034
Записей в блоге: 30
03.06.2011, 16:54 13
Цитата Сообщение от Kastaneda Посмотреть сообщение
Evg, по-моему первым делом создается таблица виртуальных ф-ций и VPTR
Я говорил не о том, как оно технически реализовано, а том, как оно идиологически должно быть устроено. При работе с виртуальными классами должна быть как минимум одна точка, где известен тип объекта - это его создание (ну и, соотвественно, конструктор). При этом базовый клас вообще ничего не должен знать о производных классах (ибо в противном случае это вообще не ООП, что имееет место быть в твоём примере из поста #11)
0
alex_x_x
бжни
2455 / 1661 / 134
Регистрация: 14.05.2009
Сообщений: 7,162
03.06.2011, 17:05 14
Цитата Сообщение от Evg Посмотреть сообщение
При этом базовый клас вообще ничего не должен знать о производных классах (ибо в противном случае это вообще не ООП, что имееет место быть в твоём примере из поста #11)
если без утопий, то например используется в паттерне шаблонный метод
0
Kastaneda
03.06.2011, 17:09
  #15

Не по теме:

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

1
Mr.X
Эксперт С++
3182 / 1709 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
03.06.2011, 17:09 16
Цитата Сообщение от Kastaneda Посмотреть сообщение
а значит в конструкторе уже можно использовать виртуальные ф-ции
На самом деле по стандарту виртуальныные функции, вызываемые в конструкторе или деструкторе, принадлежат к тому же классу, что и конструктор или деструктор. Если было бы иначе, то, как уже замечено выше, это было бы нарушением инкапсуляции.
1
kravam
быдлокодер
1709 / 896 / 105
Регистрация: 04.06.2008
Сообщений: 5,542
03.06.2011, 17:18  [ТС] 17
Kastaneda, а Вы не могли бы пояснить, в Вашем коде мне худо-бедно понятно всё. Ну то есть создаётся производный класс (сперва базовый и указатель на него переопределяется в указатель на производный (который типа есть ну или вот-вот будет) и вызывается функция производного класса)
Это понятно. Но как может вызываться функция объекта, которого не то что нет, а и быть не может?

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

Как это понимать? Я вообще теряюсь.
0
Evg
Эксперт CАвтор FAQ
19303 / 7158 / 532
Регистрация: 30.03.2009
Сообщений: 20,034
Записей в блоге: 30
03.06.2011, 17:19 18
Цитата Сообщение от Kastaneda Посмотреть сообщение
Ты про логику, а я про реализацию, которая позволяет обойти логику. На то он и C++ )))
Ну потому и получился быдлокод
0
Kastaneda
Jesus loves me
Эксперт С++
4942 / 3019 / 346
Регистрация: 12.12.2009
Сообщений: 7,622
Записей в блоге: 2
Завершенные тесты: 1
03.06.2011, 17:33 19
Цитата Сообщение от kravam Посмотреть сообщение
Kastaneda, а Вы
Ты

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

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

Не по теме:

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

0
OstapBender
584 / 523 / 75
Регистрация: 22.03.2011
Сообщений: 1,585
03.06.2011, 17:58 20
А если у нас много производных классов и для каждого нужно вызывать свою функцию?

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

самое смешное что если заменить reinterpret_cast на менее брутальное static_cast всё равно работает
0
03.06.2011, 17:58
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.06.2011, 17:58

ООП в C++: Вызов родительского конструктора с параметром при создании объекта дочернего класса
Здравствуйте! Столкнулся с такой проблемой: если есть родительский класс с...

Как убрать функцию из дочернего класса?
Представим что имеется 3 класса: A, B и C; Класс А - базовой(родительский)....

Как в конструкторе класса передать параметром указатель на функцию?
Друзья! Вот тут всё понятно, есть класс, в котором приватная функция f_0, в...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru