Russian Qt Forum
Ноябрь 23, 2024, 18:13 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Вызов метода дочернего класса  (Прочитано 11313 раз)
trot
Гость
« : Апрель 04, 2012, 14:01 »

Есть родительский класс и пронаследованный от него дочерний.
Существует ли возможность вызова метода дочернего класса из родительского. Если - да, то как?

Спасибо.
Записан
mutineer
Гость
« Ответ #1 : Апрель 04, 2012, 14:03 »

виртуальные методы
Записан
trot
Гость
« Ответ #2 : Апрель 04, 2012, 14:41 »

Вот пример, который работает не так как хочется. Что я делаю неправильно?
Код
C
class I{
public:
virtual void create()=0;
}
 
class A:public I {
public:
A(){
create();
};
~A();
virtual void create(){};
 
};
 
class B:public B{
public:
B();
~B();
virtual void create(){int i = 1+1;};
};
 
int main(int argc, char *argv[]){
B * b = new B();
}

надо чтобы сработал метод create() класса B, а не А,
можно конечно написать так
Код
C
int main(int argc, char *argv[]){
B * b = new B();
          b->create();
}
Но хотелось бы всю типовую логику записать в базовый класс, а реализацию логического действия в производном классе.


Записан
mutineer
Гость
« Ответ #3 : Апрель 04, 2012, 14:48 »

Неправильно вызывать виртуальный метод в конструкторе базового класса
« Последнее редактирование: Апрель 04, 2012, 14:53 от mutineer » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Апрель 04, 2012, 15:09 »

Когда выполняется конструктор базового класса (A) все виртуалы работают как для A, и sizeof(*this) вернет sizeof(A). Порожденный класс (B) в этот момент еще как бы "не создан"
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #5 : Апрель 04, 2012, 15:10 »

И с деструктором такая же беда.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #6 : Апрель 04, 2012, 15:19 »

Это классический пример на шаблонах:

Код
C++ (Qt)
#include <iostream>
 
template<class Derived>
class A {
  public:
     A(Derived* d){d->init();}
};
 
class B : public A<B> {
  public:
     B():A<B>(this){}
 
     void init(){std::cout << "B" << std::endl;}  
};
class C : public A<C> {
  public:
     C():A<C>(this){}
 
     void init(){std::cout << "C" << std::endl;}  
};
 
int main()
{
  B b;
  C c;
  return 0;
}
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Akon
Гость
« Ответ #7 : Апрель 05, 2012, 08:01 »

Этот подход имеет ограниченное применение, хотя такие вещи составляют уникальную мощь C++! В ООП на C++ использование этого подхода чревато трудноуловимыми багами:
Код:
#include <iostream>
#include <string>

class String
{
public:
String() : marker_(0x047F4578) {}
std::string data() const { return 0x047F4578 == marker_ ? "Constructed" : "Not constructed"; }

private:
int marker_;
};

template<class Derived>
class A
{
public:
A(Derived* d){d->init();}
};

class B : public A<B>
{
public:
B():A<B>(this){}

void init(){std::cout << "B: String member " << string_.data() << std::endl;}

private:
String string_;
};

int main()
{
B b;
return 0;
}

Т.е. мы имеем в B::init() несконструированный член B::string_! Собственно, по этой причине в С++ и не вызываются из конструкторов и деструкторов виртуальные методы, поскольку всегда есть возможность использования неинициализированных членов. В языках, где нет объектов-значений такой проблемы принципиально нет, поскольку базовый класс имеет возможность инициализировать всю память (нулями).
Записан
mutineer
Гость
« Ответ #8 : Апрель 05, 2012, 10:14 »

Собственно, по этой причине в С++ и не вызываются из конструкторов и деструкторов виртуальные методы, поскольку всегда есть возможность использования неинициализированных членов.

Они не вызываются скорее потому, что таблица виртуальных функций для дочерних классов на этапе конструктора родителя еще не построена
Записан
Akon
Гость
« Ответ #9 : Апрель 05, 2012, 11:04 »

Ну хорошо, а что мешает эту таблицу построить (таблицы виртуальных функций строятся на этапе компиляции)? То, что в конструкторе vmt pointer всегда указывает на vmt данного типа, а не дочернего, как в некоторых других языках, - это как раз самый простой способ реализации предотвращения полиморфного поведения (виртуального вызова).
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Апрель 05, 2012, 11:07 »

Т.е. мы имеем в B::init() несконструированный член B::string_! Собственно, по этой причине в С++ и не вызываются из конструкторов и деструкторов виртуальные методы, поскольку всегда есть возможность использования неинициализированных членов.
Да, все четко. Спасибо за разъяснение этого нюанса
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #11 : Апрель 16, 2012, 13:49 »

Что я ничего не понял Непонимающий

Понял одно, что в конструкторе класса унаследованного от абстрактного нельзя вызывать виртуальные методы.
Записан
RealDuke
Гость
« Ответ #12 : Апрель 16, 2012, 14:11 »

Понял одно, что в конструкторе класса унаследованного от абстрактного нельзя вызывать виртуальные методы.
Как минимум странный  и неверный вывод, рушащий весь принцип ООП Улыбающийся На этапе конструктора производного класса таблица виртуальных функций уже сформирована. Только вот зачем виртуальные функции вызывать в конструкторе (следовательно в объекте известного типа) для меня вопрос.
« Последнее редактирование: Апрель 16, 2012, 14:14 от RealDuke » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.077 секунд. Запросов: 23.