быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,691
1

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

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

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

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
02.06.2011, 21:48
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.06.2011, 21:48
Ответы с готовыми решениями:

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

Как из метода производного класса вызвать поле родительского класса
Добрый день! Помогите пожалуйста вызвать поле базового класса из метода производного класса. Код, составленный мною выводит результат...

Как вызвать метод вложенного класса в методе родительского класса
Имеется родительский класс для прорисовки графики Jogj package objects; import com.jogamp.opengl.GL2; import...

19
5 / 5 / 4
Регистрация: 05.12.2009
Сообщений: 13
03.06.2011, 00:00 2
Попробуй обратиться к объекту производного класса через указатель
C++
1
2
sin *k;
k = new sin();
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,691
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
594 / 532 / 76
Регистрация: 22.03.2011
Сообщений: 1,585
03.06.2011, 01:53 4
понял - ты хочешь вызывать из базового класса какую то версию функции объявленной в нем но переопределенной в производном ..
но ведь базовый класс не знает ни о каких других версиях этой функции ( у него своя таблица vtable в которой только адреса функций базового) -> не ясно как ты хочешь добиться такого эффекта.

пс если получится отпишись
0
 Аватар для pito211
187 / 174 / 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;
};
здесь в конструкторе обе функции вызываются
2
101 / 88 / 7
Регистрация: 17.12.2010
Сообщений: 416
03.06.2011, 08:28 6
kravam, при создании объекта производного класса, сначала вызывается конструктор базового класса (со своей функцией void f() ), а потом конструктор производного класса(опять же со своей функцией void f() ). то есть конструктор базового класса (вместе со своими функциями) вызывается всегда, а вы хотите, что бы он не вызывался что ли?
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
03.06.2011, 08:32 7
Дело в том, что виртуальность функции проявляется не всегда, а только в том случае, когда она вызывается через ссылку или указатель на базовый класс. Во всех остальных случаях функция воспринимается компилятором как невиртуальная.
0
5 / 5 / 4
Регистрация: 05.12.2009
Сообщений: 13
03.06.2011, 13:22 8
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
кстати, если бы у виртуальной функции базового класса не было бы тела, наверняка появилась бы ошибка типа "access violation"
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
03.06.2011, 15:18 9
Цитата Сообщение от tapka Посмотреть сообщение
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
Я не специалист по Си++, но мне тоже кажется, что так оно и есть. Конструктор вызывается для инициализации собственных полей, а потому конструктор может вызывать только методы, определённые в данном классе (или у родителей). Логично, что работать с виртуальными методами можно только после того, как объект уже создан, а в процессе работы конструктора объект как бы ещё не до конца создан
0
 Аватар для pito211
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 15:25 10
внутри конструктора производного класса можно работать с методами базового класса и вызывать любые свои методы
0
 Аватар для Kastaneda
5232 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
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
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 16:51 12
есть такая книга. Оформлена так, что главы там называются "советы" и в ней очень много написано как раз про то как работают все эти касты с наследоваными классами. Может кто вспомнит автора\название?
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
03.06.2011, 16:54 13
Цитата Сообщение от Kastaneda Посмотреть сообщение
Evg, по-моему первым делом создается таблица виртуальных ф-ций и VPTR
Я говорил не о том, как оно технически реализовано, а том, как оно идиологически должно быть устроено. При работе с виртуальными классами должна быть как минимум одна точка, где известен тип объекта - это его создание (ну и, соотвественно, конструктор). При этом базовый клас вообще ничего не должен знать о производных классах (ибо в противном случае это вообще не ООП, что имееет место быть в твоём примере из поста #11)
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 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
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
03.06.2011, 17:09 16
Цитата Сообщение от Kastaneda Посмотреть сообщение
а значит в конструкторе уже можно использовать виртуальные ф-ции
На самом деле по стандарту виртуальныные функции, вызываемые в конструкторе или деструкторе, принадлежат к тому же классу, что и конструктор или деструктор. Если было бы иначе, то, как уже замечено выше, это было бы нарушением инкапсуляции.
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,691
03.06.2011, 17:18  [ТС] 17
Kastaneda, а Вы не могли бы пояснить, в Вашем коде мне худо-бедно понятно всё. Ну то есть создаётся производный класс (сперва базовый и указатель на него переопределяется в указатель на производный (который типа есть ну или вот-вот будет) и вызывается функция производного класса)
Это понятно. Но как может вызываться функция объекта, которого не то что нет, а и быть не может?

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

Как это понимать? Я вообще теряюсь.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
03.06.2011, 17:19 18
Цитата Сообщение от Kastaneda Посмотреть сообщение
Ты про логику, а я про реализацию, которая позволяет обойти логику. На то он и C++ )))
Ну потому и получился быдлокод
0
 Аватар для Kastaneda
5232 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
03.06.2011, 17:33 19
Цитата Сообщение от kravam Посмотреть сообщение
Kastaneda, а Вы
Ты

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

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

Не по теме:

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

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

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

самое смешное что если заменить reinterpret_cast на менее брутальное static_cast всё равно работает
0
03.06.2011, 17:58
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.06.2011, 17:58
Помогаю со студенческими работами здесь

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

Обращение к методу дочернего класса из экземпляра родительского класса
Как обратиться к методу дочернего класса из экземпляра родительского класса? К примеру здесь как обратиться к Method, Translate static...

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

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

Ссылка на метод дочернего класса из родительского
Всем привет! Я новичок в C++. Помогите, пожалуйста, сослаться из родительского класса на метод, реализованный в дочернем классе, и,...


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

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

Редактор формул (кликните на картинку в правом углу, чтобы закрыть)
Опции темы

Новые блоги и статьи
Создаем SPA Router на чистом JavaScript
bytestream 17.02.2025
В современной веб-разработке одностраничные приложения (SPA) стали стандартом для создания динамичных и отзывчивых пользовательских интерфейсов. Ключевым компонентом любого SPA является роутер -. . .
Машинное обучение на TypeScript и TensorFlow
bytestream 17.02.2025
Машинное обучение становится все более востребованным направлением в современной разработке программного обеспечения. Интеграция искусственного интеллекта в веб-приложения открывает новые возможности. . .
Манипуляция данными EXIF и JPEG в JavaScript
bytestream 17.02.2025
В современном мире цифровой фотографии метаданные изображений играют важнейшую роль в организации и управлении медиаконтентом. Формат EXIF (Exchangeable Image File Format) - это стандарт,. . .
Как создать GUID/UUID в JavaScript
bytestream 17.02.2025
GUID (Globally Unique Identifier) и UUID (Universally Unique Identifier) - это специальные форматы 128-битных идентификаторов, которые практически гарантируют уникальность значения во времени и. . .
Что такое мышление в упрощенном смысле (моё субъективное видение, для создания модели).
Hrethgir 17.02.2025
Разумеется упрощать смысл есть. Дело в том, что я пришёл к тому выводу, что даже если я создам свой процессор (конвейер), то первое для чего смогу его использовать в качестве демонстративного. . .
Как Node.js устроен изнутри
Wired 17.02.2025
Node. js коренным образом изменил подход к веб-разработке, позволив использовать JavaScript не только в браузере, но и на стороне сервера. Созданный в 2009 году Райаном Далем, Node. js представляет. . .
Как обновить Node.js в Windows
Wired 17.02.2025
Думаю, многие разработчики сталкивались с ситуацией, когда устаревшая версия Node. js становилась источником проблем - от несовместимости с новыми пакетами до уязвимостей в безопасности. Особенно это. . .
Как обновить Node.js в MacOS
Wired 17.02.2025
В Node. js существует несколько подходов к обновлению, каждый из которых имеет свои преимущества и особенности применения. Выбор конкретного метода зависит от ваших потребностей - будь то. . .
Как обновить Node.js в Linux
Wired 17.02.2025
Обновление Node. js может показаться сложной задачей, особенно если у вас несколько проектов с разными зависимостями. Однако существует несколько надежных способов обновления, подходящих для разных. . .
[golang] 134. Gas Station
alhaos 17.02.2025
Тут нам даны два целочисленных слайса gas и cost, индексы массива представляют собой заправочные станции. а элементы gas это количество топлива на такой станции, cost это количество топлива. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru