Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > массивы классов


Автор: nns2009 1.2.2009, 18:58
У меня почему-то не создаётся массив классов, точнее создаётся, но не эксплуатируется. Я пытаюсь создать так:
Код

pastime** pases = new *pastime[2];
pases[0] = new pastime();
pases[1] = new pastime();
или так:
Код

pastime pases[2];
pases[0] = new pastime();
pases[1] = new pastime();
может я в классе что не так сделал, вот класс:
Код

class pastime
{
public:
BYTE r;
BYTE g;
BYTE b;
char* name;
char* description;
pastime()
{
r = 255;
g = 255;
b = 255;
name = "Не назначено"; //new char[13];
description = "Не назначено"; //new char[13];
return;
}
pastime(byte r1, byte g1, byte b1, char* name1, char* description1)
{
r = r1;
g = g1;
b = b1;
name = new char[strlen(name1)+1];
strcpy(name, name1);
description = new char[strlen(description1)+1];
strcpy(description, description1);
return;
}
~pastime()
{
delete [] name;
delete [] description;
return;
}
};

сама строчка создания прекрасно работает ( pastime pases[2]; ),
но потом строчки вида: pases[0].r = 120; не работают, компилятор пишет что:
1) нельзя объявить массив размером 0
2) массив не может быть типа default-int
3) нельзя объявить два массива с одинаковым именем
хотя во второй строчке я лишь назначаю свойство r первого элемента массива равным 120. 

Автор: mes 1.2.2009, 19:10
во первых массив объектов, а не классов
а во вторых как я понял, те строчки, в которых ошибки, Вы решили не показывать ?

Добавлено через 1 минуту и 57 секунд
приведите один полноценный фрагмент (не весь код, а логически полный участок кода), и ошибки которые в нем встретились
иначе получается гадание на кофейной гуще.

Автор: nns2009 1.2.2009, 19:57
Код класса приведён полностью.
В первых двух кодах не работают строчки 1 и 2, хотя по моему они абсолютно правильные.
Ещё если я наберу код
pastime pases[2];
pases[0].r = 120;
То компилятор выдаёт написанные мною выше ошибки.
На мой взгляд код правильный, но компилятор так не считает.

По мнению компилятора у меня в 1 и 2 строчке кода в первом и втором коде ошибки.

Автор: pan2004 1.2.2009, 20:00
из конструкторов/деструкторов не делают return, тк у них нет возвращаемого значения.
что касается ошибок, то возможная причина - компилятор еще не знает, что такое pastime. Например, когда этот класс еще не полностью объявлен до этих строк

Автор: nns2009 1.2.2009, 20:07
Цитата(pan2004 @ 1.2.2009,  20:00)
из конструкторов/деструкторов не делают return, тк у них нет возвращаемого значения.
что касается ошибок, то возможная причина - компилятор еще не знает, что такое pastime. Например, когда этот класс еще не полностью объявлен до этих строк

убрал return; , но ошибок ничуть не сократилось.
Код объявления массива расположен после объявления всего класса.

Автор: pan2004 1.2.2009, 20:10
точку с запятой нигде не пропустил?

Добавлено через 6 минут и 11 секунд
и потом, byte и BYTE это несколько разные типы, так что твой код компилироваться не будет

Добавлено через 7 минут и 4 секунды
И keywords типа public protected & private тоже не зря придумали. Но это так, на будущее..

Автор: mes 1.2.2009, 20:27
Цитата(nns2009 @  1.2.2009,  18:57 Найти цитируемый пост)
Код класса приведён полностью.
В первых двух кодах не работают строчки 1 и 2, хотя по моему они абсолютно правильные.
Ещё если я наберу код
pastime pases[2];
pases[0].r = 120;
То компилятор выдаёт написанные мною выше ошибки.
На мой взгляд код правильный, но компилятор так не считает.


судя по ошибкам, компилятор считает что Вы не объявили класс или пытаесь его использовать до первого объявления.
Но по участкам кода, которые Вы привели невозможно судить о порядке определений.
поэтому и просил выложить фрагмент кода из которого убрано все лишнее..
т.е должно было получиться примерно следующее :
Код

class pastime 
{
  public:
     BYTE r;

};
int main ()
{
    pastime passes[2];
    passes[0].r =120;
}

если у Вас в таком виде не работает, то остается предположение, что не определен тип BYTE;

P.S. На будущее : Вы привели кучу кода не относящегося к проблеме, не проделали никаких попыток, чтоб выявить источник проблемы
и более того скрыли те места, которые Важны для понимания Вашей проблемы.. И так как на форуме нет телепатов, ответ на вопрос такой категории очень затруднителен.
 

и кстати форматирование кода никто не запрещал  smile 

Автор: nns2009 1.2.2009, 21:17
Посмотрел на код (приведённый в сообщении выше) и заметил единственное отличие от моего:
Массив объявлён и работа производится с ним в теле функции main(), (а у меня и объявление и работа с массивом производилась вне всякой функции.)
Теперь всё работает, правда массив я всё таки объявил в глобальном виде:
массив будет использоваться и в WinMain(инициализация), и в обработчике сообщений,
а как передавать объекты из WinMain в обработчик сообщений я не знаю.
Глобальные объекты очень удобы!

Автор: pan2004 1.2.2009, 21:25
Цитата(nns2009 @  1.2.2009,  21:17 Найти цитируемый пост)
Глобальные объекты очень удобы!

Низачет. Глобальные объекты, тем более неконстантные, сакс.

Автор: EnergoHokum 1.2.2009, 23:08
Хоть конструкторы и деструкторы и не возвращают значения, однако для симметрии можно поставить "пустой" return. Это допустимо.

По теме вопроса, что сразу бросилось в глаза:

1) ты создаёшь экземпляры классов динамически (через new), а обращаешься к ним, как к статически созданным (pases[0].r=120;, надо бы pases[0]->r=120;).

2) как я понял, тебе нужен одномерный массив элементов класса, тогда создавать (и удалять) его нужно так:

Код

pastime* pases = new pastime[2];
pases[0]->r=120;
pases[1]->r=150;
delete[] pases;


Как-то так...

Автор: math64 1.2.2009, 23:29
Массив можно объявить глобальной переменной - тогда конструктор  по  умолчанию будет вызван до main(), а деструктор после main. Вне функции нельзя делать никакие манипуляции с классом:
Код

class A {
public:
int n;
A() { printf("constuctor\n"); n = 0; }
~A() { printf("destructor\n"); }
};
A a[2];
int main(int argc,char* argv[]) {
printf("main()\n");
for (int i = 0; i < 2; i++)
  a[i].n = i;
A** ppa = new A*[2];
for (int i = 0; i < 2; i++)
  ppa[i] = new A();
for (int i = 0; i < 2; i++)
  ppa[i]->n = i;
for (int i = 0; i < 2; i++)
  delete ppa[i];
delete ppa;
A* pa = new A[2];
for (int i = 0; i < 2; i++)
  pa[i].n = i;
delete[] pa;
printf("exit main()\n");
return 0;
}

А то что просили привести ошибки компилятора, то это именно то что выдаёт компилятор на английском, а не Ваш перевод, который мог быть неправильным

Автор: nns2009 2.2.2009, 15:52
Как я уже написал у меня всё заработало, но если интересны ошибки компилятора, то на такой код(написанный вне функций):
Код

pastime pases[2];
pases[0].r = 120;

компилятор выдаёт такие ошибки:
c:\microsoft visual studio 9.0\all\c++\timetable\timetable\timetable.cpp(78) : error C2466: cannot allocate an array of constant size 0
c:\microsoft visual studio 9.0\all\c++\timetable\timetable\timetable.cpp(78) : error C2143: syntax error : missing ';' before '.'
c:\microsoft visual studio 9.0\all\c++\timetable\timetable\timetable.cpp(78) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\microsoft visual studio 9.0\all\c++\timetable\timetable\timetable.cpp(78) : error C2371: 'pases' : redefinition; different basic types
        c:\microsoft visual studio 9.0\all\c++\timetable\timetable\timetable.cpp(77) : see declaration of 'pases'
сейчас я всё исправил:
вне функций идёт объявление массива:
pastime pases[2];
а в функции WinMain() - заполнение:
pases[0] = new pastime(255, 0, 0, "Отдых", "В это время работник может отдыхать.");
pases[1] = new pastime(0, 255, 0, "Работа", "В это время работник обязан работать.");

Если кому интересно почему эти 2 строки работают(объекту типа pastime присваивается указатель возвращаемый операцией new), то скажу:
в классе я перегрузил равенство и теперь могу использовать конструктор сколько мне захочется.
Код

pastime* operator=(pastime* rpas)
{
    r = rpas->r;
    g = rpas->g;
    b = rpas->b;
    delete [] name;
    name = new char[strlen(rpas->name)+1];
    strcpy(name, rpas->name);
    delete [] description;
    description = new char[strlen(rpas->description)+1];
    strcpy(description, rpas->description);
    //delete [] rpas;
    return this;
}

Автор: mes 2.2.2009, 15:59
Цитата(nns2009 @  2.2.2009,  14:52 Найти цитируемый пост)
Как я уже написал у меня всё заработало, но если интересны ошибки компилятора,

интерес к ошибкам был проявлен не из за любопытства, как Вы могли подумать, а для того чтоб лучше съорентироваться в решении Вашей же проблемы
и советы по тому как лучше оформлять вопрос давались на будущее,  на случай если у Вас опять возникнет проблема и Вы захотите прибегнуть к помощи
форумчан. 
Ну а в остальном рад за Вас, что у Вас все получилось и удачи  smile

Добавлено через 1 минуту и 1 секунду
P.S. и не забудьте пометить тему как решенную...

Автор: pan2004 2.2.2009, 16:30
nns2009, эти две строчки конечно работают, только память-то все равно утекает... На каждый new должен быть delete.
Нехорошо так делать.

Добавлено через 5 минут и 24 секунды
Мне так кажется, ты перешел с другого языка(C#, Basic whatever) на C++ и пытаешься использовать старые приемчики. Вот, например, оператор равенства переделал. Или откуда-то взял, что код вне функций будет исполняться. Но увы, это не C-way. Избавляйся от старых привычек. Те же глобальные переменные у сишников(и особенно у пользователей C++) не находятся в большом почете.

Автор: math64 2.2.2009, 16:54
Если переход с C# то нужно извавляться от НОВЫХ привычек (где сборщик мусора всё удалит). но C# не позволяет объявлять глобальные переменные.
Так же гловальные переменные не хороши тем что что-то(конструкторы) выполняется до main(), а что-то (деструкторы) после main().
Если ошибка в них, можно долго не понять где ошибка - ставишь breakpoint в начале и на выходе main(), внутри main() ошибок нет ...

Автор: nns2009 5.2.2009, 16:53
Цитата(pan2004 @ 2.2.2009,  16:30)
Мне так кажется, ты перешел с другого языка(C#, Basic whatever) на C++ и пытаешься использовать старые приемчики. Вот, например, оператор равенства переделал. Или откуда-то взял, что код вне функций будет исполняться. Но увы, это не C-way. Избавляйся от старых привычек. Те же глобальные переменные у сишников(и особенно у пользователей C++) не находятся в большом почете.

Вообще говоря C++ - первый язык программирования, который я начал изучать(Basic разве что немного изучал). Но недавно я программировал на C#(который кстати гораздо удобнее, чем C++). А как на C++ без глобальных переменных: у меня есть несколько величин, которые должны быть видны в любом месте программы: и в WinMain(инициализация), и в обработчике сообщений(графическое представление).

Автор: mrbrooks 5.2.2009, 17:02

Цитата(nns2009 @  5.2.2009,  16:53 Найти цитируемый пост)
А как на C++ без глобальных переменных: у меня есть несколько величин, которые должны быть видны в любом месте программы: и в WinMain(инициализация), и в обработчике сообщений(графическое представление). 


эта тема обсуждалась не один раз. пользуйся поиском.

Автор: pan2004 5.2.2009, 19:12
Цитата(nns2009 @  5.2.2009,  16:53 Найти цитируемый пост)
у меня есть несколько величин, которые должны быть видны в любом месте программы: 

зачем?

Цитата(nns2009 @  5.2.2009,  16:53 Найти цитируемый пост)
и в WinMain(инициализация), и в обработчике сообщений(графическое представление).

1. А static keyword на что?
2. WinMain + WndProc isn't the OOP-way. Это осталось от Си (от сишного АПИ Windows). В C++ используются кроме этого библиотеки типа MFC, Qt etc.

Автор: Torsten 5.2.2009, 19:14
Цитата(nns2009 @  5.2.2009,  16:53 Найти цитируемый пост)
. А как на C++ без глобальных переменных: у меня есть несколько величин, которые должны быть видны в любом месте программы: и в WinMain(инициализация), и в обработчике сообщений(графическое представление).

ключевое слово для поиска : синглтон

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)