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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 35, средняя оценка - 4.66
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,470
#1

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

02.06.2011, 21:48. Просмотров 4818. Ответов 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
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как вызвать виртуальную функцию из дочернего класса, если она определена и вызывается в конструкторе РОДИТЕЛЬСКОГО класса? (C++):

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

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

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

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

Почему вызывается перегрузка виртуальной функции из приватной секции дочернего класса? - C++
Как вообще такое происходит class A { public: virtual void foo(){std::cout&lt;&lt;&quot;A\n&quot;; } }; class B:public A { private: ...

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

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

пс если получится отпишись
0
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;
};
здесь в конструкторе обе функции вызываются
1
no0ker
101 / 88 / 4
Регистрация: 17.12.2010
Сообщений: 416
03.06.2011, 08:28 #6
kravam, при создании объекта производного класса, сначала вызывается конструктор базового класса (со своей функцией void f() ), а потом конструктор производного класса(опять же со своей функцией void f() ). то есть конструктор базового класса (вместе со своими функциями) вызывается всегда, а вы хотите, что бы он не вызывался что ли?
0
Mr.X
Эксперт С++
3049 / 1694 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
03.06.2011, 08:32 #7
Дело в том, что виртуальность функции проявляется не всегда, а только в том случае, когда она вызывается через ссылку или указатель на базовый класс. Во всех остальных случаях функция воспринимается компилятором как невиртуальная.
0
tapka
3 / 3 / 1
Регистрация: 05.12.2009
Сообщений: 13
03.06.2011, 13:22 #8
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
кстати, если бы у виртуальной функции базового класса не было бы тела, наверняка появилась бы ошибка типа "access violation"
0
Evg
Эксперт CАвтор FAQ
17934 / 6162 / 409
Регистрация: 30.03.2009
Сообщений: 16,918
Записей в блоге: 27
03.06.2011, 15:18 #9
Цитата Сообщение от tapka Посмотреть сообщение
немного пораздумав, прихожу к выводу, что возможности обратиться к методу производного класса быть не может. как и в принципе вызова переопределенной виртуальной функции из конструктора.
в момент, когда конструктор базового класса вызывает функцию f(), объект производного класса еще не создан и, соответственно, его метод вызван быть не может.
Я не специалист по Си++, но мне тоже кажется, что так оно и есть. Конструктор вызывается для инициализации собственных полей, а потому конструктор может вызывать только методы, определённые в данном классе (или у родителей). Логично, что работать с виртуальными методами можно только после того, как объект уже создан, а в процессе работы конструктора объект как бы ещё не до конца создан
0
pito211
186 / 173 / 8
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 15:25 #10
внутри конструктора производного класса можно работать с методами базового класса и вызывать любые свои методы
0
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,274
Записей в блоге: 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 / 8
Регистрация: 22.03.2010
Сообщений: 612
03.06.2011, 16:51 #12
есть такая книга. Оформлена так, что главы там называются "советы" и в ней очень много написано как раз про то как работают все эти касты с наследоваными классами. Может кто вспомнит автора\название?
0
Evg
Эксперт CАвтор FAQ
17934 / 6162 / 409
Регистрация: 30.03.2009
Сообщений: 16,918
Записей в блоге: 27
03.06.2011, 16:54 #13
Цитата Сообщение от Kastaneda Посмотреть сообщение
Evg, по-моему первым делом создается таблица виртуальных ф-ций и VPTR
Я говорил не о том, как оно технически реализовано, а том, как оно идиологически должно быть устроено. При работе с виртуальными классами должна быть как минимум одна точка, где известен тип объекта - это его создание (ну и, соотвественно, конструктор). При этом базовый клас вообще ничего не должен знать о производных классах (ибо в противном случае это вообще не ООП, что имееет место быть в твоём примере из поста #11)
0
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 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
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.06.2011, 17:09
Привет! Вот еще темы с ответами:

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

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

Как построить экземпляр дочернего класса на основе готового экземпляра базового класса? - C++
Если уже есть готовый объект базового класса. Могу я построить экземпляр дочернего на его основе, (напр., получив такой базовый объект...

Почему в списке инициализации конструктора дочернего класса нельзя вызывать конструктор родительского через его пространство имён? - C++
Есть класс D и от него порождён класс Wd Тут вот например всё работает корректно (использую обращение ч/з пространство имён класса &quot;D::&quot; ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
03.06.2011, 17:09
Ответ Создать тему
Опции темы

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