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

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

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

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 27.05.2010, 18:42   #1
Vang
 
Регистрация: 27.05.2010
Сообщений: 6
По умолчанию Проблема с созданием двумерного массива из объектов производных классов

Доброго времени суток. Для начала обрисую ситуацию. Мне нужно динамически создать двумерный массив из трех классов, для этого я создал некий класс с интерфейсом и остальные классы просто наследовал от него. Допустим, у меня получился массив 3х3 (как он получился смотрите дальше), но когда мне нужно достучаться до данных находящихся не в нулевом столбце программа вылетает с ошибкой 0xC0000005. Вот упрощенный код, который отражает суть проблемы:
Код:
#include <iostream>
using namespace std;

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

class B : public A
{
	public:
		B(){setInput();}

		virtual void setInput(){b = 'b';}
		virtual char getInput(){return b;}
	private:
		char b;
};

int _tmain(int argc, _TCHAR* argv[])
{
	A** objMy;

	objMy = new A*[3];

	for(int i = 0; i < 3; i++)
	{
		objMy[i] = new B[3];
		for(int j = 0; j < 3; j++)
//В следующей строке я пробегаюсь по строке массива и на второй итерации вылетает ошибка
			cout << objMy[i][j].getInput();					
		cout << "\n";
	}

	for(int i=0; i<3; i++)
		delete [] objMy[i];

	cin.get();
	return 0;
}
Vang вне форума Ответить с цитированием
Старый 27.05.2010, 18:51   #2
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Код:
#include <iostream>
using namespace std;

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

class B : public A
{
	public:
		B(){b = 'b';}

		virtual void setInput(){}
		virtual char getInput(){return b;}
	private:
		char b;
};

int main()
{
	A* objMy[3][3];
	int i, j;

	for(i = 0; i < 3; i++)
		for(j = 0; j < 3; j++)
			objMy[i][j] = new B();
	
	for(i = 0; i < 3; i++)
		for(j = 0; j < 3; j++)
			cout << objMy[i][j]->getInput();	

	for(i = 0; i < 3; i++)
		for(j = 0; j < 3; j++)
			delete objMy[i][j];

	cin.get();
	return 0;
}

Последний раз редактировалось profi; 27.05.2010 в 21:19.
profi вне форума Ответить с цитированием
Старый 27.05.2010, 19:34   #3
Vang
 
Регистрация: 27.05.2010
Сообщений: 6
По умолчанию

Это понятно, что ваш код будет работать. И понятно, что objMy[i] = new A[3]; нельзя, но objMy[i] = new A*[3]; можно, потому что я тут создаю не объекты абстрактного класса, а массив указателей на абстрактный класс. Тем более приведенные изменения не решают проблемы, смысл в том, чтобы оперировать объектами производного класса, через базовый класс.
Vang вне форума Ответить с цитированием
Старый 27.05.2010, 19:46   #4
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Я против этой строки
Код:
objMy[i] = new A*[3];
что то говорил? Vang переделал. Пост №2.
profi вне форума Ответить с цитированием
Старый 27.05.2010, 20:11   #5
Vang
 
Регистрация: 27.05.2010
Сообщений: 6
По умолчанию

нет, я просто подумал, что мы друг друга не поняли) Спасибо, это решение. А ты не мог бы подсказать, почему мой код не работает? В чем там ошибка?
Vang вне форума Ответить с цитированием
Старый 27.05.2010, 20:13   #6
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Код:
#include <iostream>

class A
{
public:

	virtual ~A() {}

	virtual char get() const = 0;
};

class B : public A
{
public:

	char get() const { return 'B'; }
};


int main( int, char ** )
{
	A ** array = new A * [3];
	for ( int i = 0; i < 3; ++i ) array[i] = new B[3];
	
	for ( int i = 0; i < 3; ++i )
		for ( int j = 0; j < 3; ++j )
			std::cout << array[i][j].get();
	
	for ( int i = 0; i < 3; ++i ) delete [] array[i];
	delete [] array;

	std::cin.get();

	return 0;
}
Пашет

А я знаю, что не так!
В конструкторе не должен вызываться чисто виртуальный метод.


Vang, profi, у вас двоих будет падать вот тут: B(){setInput();} потому что объект класса B ещё не создан, поэтому вызывается A::setInput()

Последний раз редактировалось Carbon; 27.05.2010 в 20:25.
Carbon вне форума Ответить с цитированием
Старый 27.05.2010, 21:12   #7
Vang
 
Регистрация: 27.05.2010
Сообщений: 6
По умолчанию

А как это объясняет, что объекты в нулевом столбце создаются нормально (нормально в смысле b инициализируется и до нее можно потом достучаться)? Да и падает, лично у меня, не на setInput(), а на getInput(), в отличие от profi, у него все работает.
Vang вне форума Ответить с цитированием
Старый 27.05.2010, 21:15   #8
profi
Участник клуба Подтвердите свой е-майл
 
Регистрация: 19.11.2007
Сообщений: 1,022
По умолчанию

Carbon действительно +1 . Не подумал. Вызов метода setInput(); будет осуществлен через таблицу виртуальных функций, а так как объект B() создан еще не до конца, в таблице ничего не будет.
profi вне форума Ответить с цитированием
Старый 27.05.2010, 21:58   #9
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Цитата:
Сообщение от Vang Посмотреть сообщение
А как это объясняет, что объекты в нулевом столбце создаются нормально (нормально в смысле b инициализируется и до нее можно потом достучаться)? Да и падает, лично у меня, не на setInput(), а на getInput(), в отличие от profi, у него все работает.
Вообще-то падает не всегда там, где произошло что-то страшное, а может упасть после на безобидной операции.
Например, мы можем выйти за предел массива и всё будет хорошо. Но потом в совсем другой части программы может упасть.
А то, что у него не падает, не значит что код рабочий. Компилятор ещё и оптимизировать умеет и разные версии по-разному.
Carbon вне форума Ответить с цитированием
Старый 28.05.2010, 13:13   #10
Vang
 
Регистрация: 27.05.2010
Сообщений: 6
По умолчанию

Carbon к сожалению это не решило проблему, если даже убрать из конструктора чисто виртуальный метод, то программа все равно подает на том же месте, т.е. на getInput(). Вот код:
Код:
#include <iostream>
using namespace std;

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

class B : public A
{
	public:
		B(){setInput();}

		virtual void setInput_B(){b = 'B';}
                void setInput(){b = 'b';}
		virtual char getInput(){return b;}
	private:
		char b;
};

int _tmain(int argc, _TCHAR* argv[])
{
	A** objMy;

	objMy = new A*[3];

	for(int i = 0; i < 3; i++)
	{
		objMy[i] = new B[3];
		for(int j = 0; j < 3; j++){
                        objMy[i][j].setInput_B();
			cout << objMy[i][j].getInput();//Место падения
               }					
		cout << "\n";
	}

	for(int i=0; i<3; i++)
		delete [] objMy[i];

	cin.get();
	return 0;
}
Да и если, изменить немного в вашем коде класс B
Код:
class B : public A
{
public:
	B(){b = 'b';}
	char get() const { return b; }

private:
	char b;
};
то программа работать перестанет.

Последний раз редактировалось Vang; 28.05.2010 в 13:24.
Vang вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 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