Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.05.2010, 13:41   #11
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Vang у Carbon код правильный. Кстати, вызывать виртуальные методы в конструкторе безсмысленно и не верно.

P.S. Свой пример я еще вчера подправил.
profi вне форума Ответить с цитированием
Старый 28.05.2010, 14:37   #12
Vang
 
Регистрация: 27.05.2010
Сообщений: 6
По умолчанию

profi А я и не говорил, что у него код неправильный. Я говорю про то, что если попытать достучаться до элемента данных, то программа вылетает с ошибкой.

Цитата:
Кстати, вызывать виртуальные методы в конструкторе безсмысленно и не верно.
Хорошо, это моя первая программа где используется наследование, я всех тонкостей еще не знаю, и я тоже читал комментарий Carbon'а.

Последний раз редактировалось Vang; 28.05.2010 в 15:04.
Vang вне форума Ответить с цитированием
Старый 28.05.2010, 15:15   #13
Syuf
Форумчанин
 
Аватар для Syuf
 
Регистрация: 02.02.2010
Сообщений: 599
По умолчанию

Если еще немного упростить программу, то получится:
Код:
#include <iostream>
using namespace std;

class A 
{
	public:	
		virtual ~A(void) {}
		virtual char getInput() = 0;
};

class B : public A
{
	public:
		B() { b='b'; }
		virtual char getInput() { return b; }
		char b;
};

int main()
{
	A* objMy;

	objMy = new B[3];

	cout<<objMy[0].getInput()<<"   "<<objMy[1].getInput()<<"   "<<objMy[2].getInput()<<endl;

	delete [] objMy;
	cin.get();
	return 0;
}
Но это также вылетает с той же ошибкой. Чтобы исправить, надо сделать:
Код:
#include <iostream>
using namespace std;

class A 
{
	public:	
		virtual ~A(void) {}
		virtual char getInput() = 0;
protected:
	char b;
};

class B : public A
{
	public:
		B() { b='b'; }
		virtual char getInput() { return b; }
};

int main()
{
	A* objMy;

	objMy = new B[3];

	cout<<objMy[0].getInput()<<"   "<<objMy[1].getInput()<<"   "<<objMy[2].getInput()<<endl;

	delete [] objMy;
	cin.get();
	return 0;
}
Смотрите, что получается: вы выделяете динамически память для массива элементов типа B с указателя типа 'указатель на A', то есть на прямой базовый класс. Это можно сделать, но теперь эти объекты будут обладать функциональностью базового класса, то есть класса A, но в нем не существует данного-члена 'char b', к которому вы обращаетесь посредством виртуальной функции. Поэтому вы получаете ошибку.
Действительно: если распечатать адреса объектов из первого примера, то получится, что они отличаются на 4 байта, сколько бы вы не добавляли данных-членов в класс B.
"Лишь то читается легко, что написано с трудом; что в час написано, то в час и позабыто."
Syuf вне форума Ответить с цитированием
Старый 28.05.2010, 16:02   #14
still_alive
Great Code Monkey
Форумчанин
 
Аватар для still_alive
 
Регистрация: 09.08.2007
Сообщений: 533
По умолчанию

Цитата:
Vang, profi, у вас двоих будет падать вот тут: B(){setInput();} потому что объект класса B ещё не создан, поэтому вызывается A::setInput()
Не будет тут падать. Хоть объект класса B еще и не создан, VPTR уже указывает на нужную таблицу виртуальных функций.

Цитата:
Вызов метода setInput(); будет осуществлен через таблицу виртуальных функций, а так как объект B() создан еще не до конца, в таблице ничего не будет.
VTBL заполняется для каждого класса на этапе компиляции. VPTR инициализируется после вызова конструкторов базовых классов, но до списка инициализации, поэтому все будет нормально.

Цитата:
Кстати, вызывать виртуальные методы в конструкторе безсмысленно и не верно.
Вызов виртуальных методов в конструкторе тождественен вызову обычных. Никакого криминала нет.

Код:
// тут мы создаем массив указателей на A(!)
    A** objMy = new A*[3];

    for(int i = 0; i < 3; i++) {
        // а на деле каждый указатель - массив из B(!)
        objMy[i] = new B[3];
        for(int j = 0; j < 3; j++)
            // тут КОСЯК!!!
            // адресную арифметику применять нельзя!
            // Addr(objMy[i][j]) = Addr(objMy) + (i*3+j)*sizeof(A!!!хотя у нас там B);
            // sizeof(B) > sizeof(A)
            // поэтому при i=0 и j=0 итерации все работает нормально, в другом
            // случае мы утыкаемся непонятно куда (а в данном случае на b_ при i=0,j=1),
            // откуда берем неправильный this
            // и вызываем не нужную виртуальную функцию, а не пойми что, что приводит к краху
            cout << objMy[i][j].getInput();

Последний раз редактировалось still_alive; 28.05.2010 в 17:06.
still_alive вне форума Ответить с цитированием
Старый 28.05.2010, 16:53   #15
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Цитата:
Цитата:
Вызов метода setInput(); будет осуществлен через таблицу виртуальных функций, а так как объект B() создан еще не до конца, в таблице ничего не будет.
VTBL заполняется для каждого класса на этапе компиляции. VPTR инициализируется после вызова конструкторов производных классов, но до списка инициализации, поэтому все будет нормально.
Ответ конечно интересный. Читал в разных статьях совсем иное про конструкторы и вызовы виртуальных методов в них.
profi вне форума Ответить с цитированием
Старый 28.05.2010, 17:04   #16
still_alive
Great Code Monkey
Форумчанин
 
Аватар для still_alive
 
Регистрация: 09.08.2007
Сообщений: 533
По умолчанию

2profi
Сорри, опечатался. Там конечно не производных, а базовых.

http://www.devdoc.ru/index.php/conte...w/cpp_init.htm
http://www.devdoc.ru/index.php/conte...rtual_base.htm
still_alive вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с созданием динамических объектов. (Delphi7) Dalagardi Помощь студентам 2 15.03.2010 17:15
Передать массив базового абстрактного класса функциям производных классов mishutka999 Общие вопросы C/C++ 2 01.12.2009 14:08
проблема создания массива объектов Meduzza Общие вопросы C/C++ 3 28.05.2009 05:07
Создание классов и использование объектов классов при написании программ в среде C++. Frozen inside Помощь студентам 0 16.04.2009 23:18
Delphi: Проблема с созданием объектов Omedus Помощь студентам 4 08.08.2008 18:42