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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 14.12.2019, 08:38   #1
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию массив из объектов класса

Здравствуйте.
Код;
Код:
#include <iostream>
#include <malloc.h>

class Class2{
public:
    int b;

	Class2(int b){
		std::cout << "class2 constructor" << std::endl;
		this->b = b;
	}

	~Class2(){
		std::cout << "class2 destructor" << std::endl;
	}
};

class Class1{
public:
    float x;
    float y;
    float z;
    Class2* c2;

	Class1(float x, float y, float z){
		std::cout << "class1 constructor" << std::endl;
		this->x = x;
		this->y = y;
		this->z = z;
		c2 = new Class2(8);
	}

	~Class1(){
		std::cout << "class1 destructor" << std::endl;
		delete c2;
    }
};

class ClassData{
public:
    Class1* c1;

	ClassData(){
		std::cout << "class data constructor" << std::endl;
		len = 7;
                c1 = (Class1*)malloc(sizeof(Class1) * len);
		c1[0] = new Class1(0.0, 1.0, 2.87);
	}

	~ClassData(){
		std::cout << "class data destructor" << std::endl;
		delete c1;
	}

private:
    int len;
};

class TestClass{
public:
    ClassData* data;
    int a;

	TestClass(int a){
		std::cout << "testclass constructor" << std::endl;
		this->a = a;
		data = new ClassData();
	}

	~TestClass(){
		std::cout << "testclass destructor" << std::endl;
		delete data;
	}

	void PrintInfo(){
		std::cout << "a equals " << a << std::endl;
	}

};

TestClass *tc;

int main(){
    tc = new TestClass(7);
    std::cout << "z= " << tc->data->c1[0]->c2->b << std::endl;
    tc->PrintInfo();
    delete tc;
	return 0;
}
В классе ClassData нужно создать массив (статический или динамический) из объектов класса Class1.
Но компилятор не дает выполнить строчку
Код:
		c1[0] = new Class1(0.0, 1.0, 2.87);
возникает ошибка: error: no match for 'operator=' (operand types are 'Class1' and 'Class1*'). Не пойму, что именно его не устраивает. Почему типы разные?
А если сделать так:
Код:
		c1[0] = Class1(0.0, 1.0, 2.87);
то программа компилируется и работает, но Class2 создается и сразу уничтожается (его деструктор срабатывает сразу после конструктора).
Таким образом получается, что переменная b в классе Class2 будет содержать мусор.
Как правильно создать массив из объектов класса?

Последний раз редактировалось BLACK_RAIN; 14.12.2019 в 08:44.
BLACK_RAIN вне форума Ответить с цитированием
Старый 14.12.2019, 09:53   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Код:
class CSomeClass;
CSomeClass * array = new CSomeClass[123];
У класса должен быть конструктор по умолчанию.
waleri вне форума Ответить с цитированием
Старый 14.12.2019, 10:51   #3
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

del

Последний раз редактировалось BLACK_RAIN; 14.12.2019 в 11:28.
BLACK_RAIN вне форума Ответить с цитированием
Старый 14.12.2019, 11:27   #4
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

кажется, дошло. При создании массива, все его элементы создаются автоматически и для каждого выполняется конструктор. Не понимаю, зачем это сделано?
Как тогда удалить из массива ненужные более элементы или добавить новые?
BLACK_RAIN вне форума Ответить с цитированием
Старый 14.12.2019, 12:16   #5
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Не понимаю, зачем это сделано
для инициализации, это же очевидно

если компилятор поддерживает современные стандарты, то при создании динамического массива можно передать параметры в конструктор (список инициализации в фигурных скобках)
Код:
CSomeClass* array = new CSomeClass[123]{8};
Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Как тогда удалить из массива ненужные более элементы или добавить новые
пользоваться std::vector

ну, или, если такое хобби и много свободного времени, то изобретать свои велосипеды и героически их отлаживать

Последний раз редактировалось Алексей1153; 14.12.2019 в 12:18.
Алексей1153 вне форума Ответить с цитированием
Старый 14.12.2019, 12:57   #6
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
для инициализации, это же очевидно
Почему нельзя создать элементы равные NULL, а инициализацию возложить на программиста? Это же логично и дает возможность создавать каждый элемент сразу с нужными параметрами, а не менять их уже после того.
Из каких соображений было решено инициализировать все элементы сразу при создании массива?
Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
если компилятор поддерживает современные стандарты, то при создании динамического массива можно передать параметры в конструктор (список инициализации в фигурных скобках)
Код:
CSomeClass* array = new CSomeClass[123]{8};
Это практически ничего не дает, ведь все элементы будут созданы с одинаковыми параметрами.

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение

пользоваться std::vector
при чем тут векторы?
BLACK_RAIN вне форума Ответить с цитированием
Старый 14.12.2019, 13:48   #7
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,330
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Не понимаю, зачем это сделано?
Потому что когда создается класс должен быть вызван его конструктор.

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Как тогда удалить из массива ненужные более элементы или добавить новые?
Никак - память выделеннoю оператором new можно только удалять.
Обходят это созданием нового массива с пустыми элементами, скопировать нужное из старого и удалить старый.

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Почему нельзя создать элементы равные NULL
Почему нельзя, можно, кто вам мешает... сделайте так, чтоб конструктор по умолчанию инициализировал ваш объект в NULL, что бы это не значило...
Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Почему типы разные?
Вы понимаете разницу между 'Class1' и 'Class1*'?
waleri вне форума Ответить с цитированием
Старый 14.12.2019, 13:54   #8
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Почему нельзя создать элементы равные NULL, а инициализацию возложить на программиста
NULL - имеет тип void* . Не нужно путать со значением 0.


Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Это же логично и дает возможность создавать каждый элемент сразу с нужными параметрами
всё заполнить нулями - это с нужными разве? Для этого есть инициализация - в конструкторе по умолчанию или (по новому стандарту) сразу у полей класса/структуры

Код:
struct my_struct
{
    int a=0;
    char* p=0;
    std::string s{"123"};
};
Можно, конечно, создавать объект, выделив ему память, заполненную мусором (то есть, без инициализации. Например, буфер, который будет тут же чем-то заполнен), но это чревато ошибками. И обычно этого и не требуется, обычно инициализация чем-либо необходима.
Заполнение всё нулями - это тоже инициализация (для тривиальных объектов подходит). Но нули - это не мусор, это конкретные значения. Ими тоже нужно ЗАПОЛНЯТЬ, сами они там не образуются на месте мусора. Это тоже отдельное действие, это инициализация.


Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
ведь все элементы будут созданы с одинаковыми параметрами.
будет вызван конструктор. Если ничего не указать - то всё равно будет вызван конструктор (по умолчанию)


Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
при чем тут векторы?
это ответ на вопрос -
Цитата:
Сообщение от BLACK_RAIN Посмотреть сообщение
Как тогда удалить из массива ненужные более элементы или добавить новые
Код:
class Class2
{
public:
	int b=0;

	Class2()
	{
	}

	Class2(int b)
		:b(b)
	{
	}
};


std::vector<Class2> vec(10,{22});//массив из 10 элементов, инициализированных значением 22
vec.erase(vec.begin()+5);//удалили элемент с индексом 5
vec.insert(vec.begin(),Class2{111});//в начало вставили новый элемент, в конструктор передали 111
Алексей1153 вне форума Ответить с цитированием
Старый 14.12.2019, 14:26   #9
BLACK_RAIN
Форумчанин
 
Регистрация: 13.02.2012
Сообщений: 867
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Потому что когда создается класс должен быть вызван его конструктор.
Я имел ввиду, чтобы при создании массива контрукторы элементов вообще не вызывались. А вызывал их сам программист при необходимости.

Цитата:
Сообщение от waleri Посмотреть сообщение
Почему нельзя, можно, кто вам мешает... сделайте так, чтоб конструктор по умолчанию инициализировал ваш объект в NULL
Я говорил о том, чтобы NULL была сама ячейка массива. Чтобы потом программист сам создавал экземпляр класса и клал его в нужную ячейку массива. Я не знаю, как еще проще объяснить. В других языках это сделано именно так и это очень логично. Разве в С++ так нельзя? Тогда получается, что лучше использовать структуры вместо классов? Размер массива структур вроде можно менять динамически и удалять/добавлять элементы.
Цитата:
Сообщение от waleri Посмотреть сообщение
Вы понимаете разницу между 'Class1' и 'Class1*'?
Понимаю. Но когда я это писал, я не знал, что все элементы классов в массиве создаются автоматически. А если в такой массив нельзя добавить/удалить элемент, то я не понимаю, для каких целей вообще создавать такие массивы.
BLACK_RAIN вне форума Ответить с цитированием
Старый 14.12.2019, 14:33   #10
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

BLACK_RAIN, структуры и классы ничем не отличаются с точки зрения компилятора (дефолтный public/private за отличие можно не считать)

то, что хочешь получить, это массив указателей. Конечно можно

Код:
Class1** a=new Class1* [10]{nullptr};
Алексей1153 вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Динамический массив объектов класса, C++ OmegaBerkut Общие вопросы C/C++ 16 27.11.2017 15:48
Класс содержащий массив объектов другого класса Cli Вероника99 Общие вопросы C/C++ 14 28.05.2016 13:52
Шаблонный массив объектов класса - C++ Андрей Иванов Помощь студентам 2 01.10.2015 17:07
Массив объектов класса. zipwind Общие вопросы C/C++ 8 01.05.2011 20:56
динамический массив объектов класса. С++ Шиншилка Помощь студентам 8 25.04.2011 17:58