до этого я справлялся, здесь я пытаюсь создать свой собственный контейнерный класс, используя vector. Мне это нужно для моей работы. я использую кодовые блоки 10.05
class myclass
{
public :
vector<myclass> array;
char * classname;
...
Проблема в том, что мои данные моего класса хорошо отображается на экране, если его удаление не происходит в деструкторе. Моя функция show () отображает нечетные символы, если я удаляю имя класса. Я полагаю, что это происходит из моего метода построения объекта, и вопрос диапазона, когда я передаю их в качестве аргумента.
myclass::~myclass()
{
//if(classname) delete [] classname;
}
И вот как это инициализируется в конструктор:
myclass::myclass(long lvl = 0, const char name[] = "undefined")
:ID(++ ID_counter)
{
level = lvl;
int namelength = strlen(name);
classname = new char[namelength + 1];
strcpy(classname, name);
}
add_content (const myclass & с) предполагается сделать копию элементов c.array и «push_back» их в массиве this->
Я случайно выяснил, что мы можем поместить объект без имени в качестве параметра: mycontainer.add_content (MyClass (3,5));
это работает, но я скептически отношусь к объему, который должен иметь
> int main()
> {
> myclass mycontainer(0);
> mycontainer.add_content(myclass(3,5));
> ...
Вот полный код:
#include <vector>
#include <iostream>
using namespace std;
class myclass
{
public :
vector<myclass> array;
static long ID_counter;
long ID;
long level;
char * classname;
myclass(int n, long lvl, const char name[]); //push_back n elements, lvl = 0, name = "undefined"myclass(long lvl, const char name[]); //lvl = 0, name = "undefined"myclass::~myclass();
void set_level(long lvl); //recursive function, go down the tree
void add(int n); //push_back n elements
void add(const myclass & c); //push_back and set back the levels
void add_content(const myclass & c); //push_back all the c.array[i] and set back the levels
void show();
template <typename T> myclass & operator[](const T it){ return array[it]; }
};
long myclass::ID_counter = 0;
myclass::myclass(long lvl = 0, const char name[] = "undefined")
:ID(++ ID_counter)
{
level = lvl;
int namelength = strlen(name);
classname = new char[namelength + 1];
strcpy(classname, name);
}
myclass::myclass(int n, long lvl, const char name[] = "undefined")
:ID(++ ID_counter)
{
level = lvl;
int namelength = strlen(name);
classname = new char[namelength + 1];
strcpy(classname, name);
for(int i = 0; i < n; i++) array.push_back( myclass(this->level + 1) );
}
myclass::~myclass()
{
//if(classname) delete [] classname; //there is the point !
}
void myclass::add(int n = 1)
{
for(int i = 0; i < n; i++) array.push_back( myclass(level + 1) );
}
void myclass::add(const myclass & c)
{
array.push_back(c);
array[array.size() - 1].set_level(level + 1);
}
void myclass::add_content(const myclass & c)
{
for(int i = 0; i < c.array.size(); i++)
{
array.push_back(c.array[i]);
array[array.size() - 1].set_level(level + 1);
}
}
void myclass::set_level(long lvl)
{
level = lvl;
for(int i = 0; i < array.size(); i++) array[i].set_level(level + 1);
}
void myclass::show()
{
cout << "ID : " << ID << "\tLvl : " << level << "\t Classname : " << classname << endl;
}
int main()
{
myclass mycontainer(0); //ground level
mycontainer.add_content(myclass(3,5)); //the 3 elements level 5 should be reset to 0+1
mycontainer.show();
for(int i = 0; i < mycontainer.array.size(); i++)
{
mycontainer[i].show();
for(int j= 0; j < mycontainer[i].array.size(); j++)
mycontainer[i][j].show();
}
cout << "\ncheckpoint\n";
system("PAUSE"); //press any key to crash!
return 0;
}
Вот нет удаления * имя класса в деструкторе, программа разрисовывает это:
ID : 1 Lvl : 0 Classname : undefined
ID : 3 Lvl : 1 Classname : undefined
ID : 4 Lvl : 1 Classname : undefined
ID : 5 Lvl : 1 Classname : undefined
checkpoint
Appuyez sur une touche pour continuer...
с удалением и некоторые плохие персонажи появляются с треском:
ID : 1 Lvl : 0 Classname : undefined
ID : 3 Lvl : 1 Classname : ░(?
ID : 4 Lvl : 1 Classname : ░(?
ID : 5 Lvl : 1 Classname : ░(?
checkpoint
Appuyez sur une touche pour continuer...
Process returned -1073741819 (0xC0000005) execution time : 29.651 s
Press any key to continue.
Я пытался изучить некоторые принципы аргументов и указателей, но этот язык слишком эмпирический и не имеет смысла. Спасибо за помощь.
У вас есть необработанный указатель, и вы не определили конструктор копирования или оператор присваивания. Это означает, что вы получаете автоматически сгенерированные версии, то, что вам не нужно. Просмотрите Правило Трех.
Решение № 1: Реализуйте правильный конструктор копирования и оператор присваивания.
Решение № 2: Изменить char * classname
в std::string classname
, Теперь автоматически сгенерированный конструктор копирования и оператор присваивания будут работать. Дополнительное преимущество: вам не нужно использовать new
вам не нужно использовать delete
,
Вы должны определить конструктор копирования.
Мой отладчик выдает ошибку здесь:
for(int i = 0; i < n; i++) array.push_back( myclass(this->level + 1) );
мы видим здесь, что новый объект myclass
создается, затем копируется (клонируется) в array
, тогда оригинал уничтожается, как и любая локальная переменная.
Итак, у нас есть два экземпляра с одним и тем же указателем: один уничтожен, другой внутри array
, созданный по умолчанию конструктор копирования, который копирует только необработанную память. Итак, экземпляр внутри array
недействителен, поскольку деструктор уже был запущен на нем.
КОД
Следующий дополнительный конструктор решит ситуацию:
myclass::myclass(const myclass& other)
:ID(++ ID_counter)
{
level = other.level;
int namelength = strlen(other.classname);
classname = new char[namelength + 1];
strcpy(classname, other.classname);
}
(выше это то, что называется «конструктор копирования»; да, конечно, вы должны соблюдать «правило трех», чтобы избежать всех потенциальных ошибок)