Шаблоны
T *object;
public:
T *next;
T *prev;
Node();
Node(T);
};
template <class T> Node<T>::Node(){
object = 0;
next = 0;
prev = 0;
}
template <class T> Node<T>::Node(T obj){
object = &obj;
next = &obj;
prev = &obj;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
class List{
public:
Node <class T> *n;
Node <class T> *curent;
List();
List(Node <class T>);
T* ins(T);
T* del(T);
};
List::List(){
curent = 0;
n = 0;
}
List::List(Node<T> node){
curent = &node;
n = &node;
}
T* List::ins(T obj){
Node <T> nNode(obj);
List nList(nNode);
//...
return *obj;
}
Компилятор орет на выделенную строку: error C2664: '__thiscall Node<class T>::
Node<class T>(class T)' : cannot convert parameter 1 from 'class T' to 'class T'
Что то я никак не вьеду, что ему не нравится...
T *object;
public:
Node<T> *next;
Node<T> *prev;
Node();
Node(T);
};
...
Так, имхо, правильнее будет.
Ну, и List, конечно, шаблонным надо сделать.
Node <T> nNode(obj);
List <T> nList(nNode);
if(nList->curent==0){
curent = &nNode;
curent->next = &nNode;
curent->prev = &nNode;
}
else{
curent->next = &nNode;
nNode->prev = curent;
}
return *obj;
}
matrix m(3,3);
List <matrix> list();
}
Так вот когда программа выполняется, то выделенная строка вобще как-то игнорируется и отладчик через нее перескакивает, как будто ее нет. И если написать так:
matrix m(3,3);
List <matrix> list();
list.ins(m);
}
то выдается ошибка left of '.ins' must have class/struct/union type. тоесть List не является классом ?
Попробуй так:
matrix m(3,3);
List <matrix> list;
}
double **mass;
public:
int dim1;
int dim2;
matrix(int d1, int d2);
matrix(const matrix &);
~matrix();
double get(int i, int j){
return mass[j];
};
double set(int i, int j, double value){
mass[j]=value;
return mass[j];
};
bool ifSym();
void out();
matrix makeSingle();
matrix trans();
friend matrix operator+ (const matrix&, const matrix&);
friend matrix operator- (const matrix&, const matrix&);
friend matrix operator* (const matrix&, const matrix&);
};
matrix::matrix(int d1, int d2){
dim1 = d1;
dim2 = d2;
mass = new double* [dim1];
for (int i=0; i<dim1; i++){
mass = new double[dim2];
}
for(i = 0; i<dim1; i++){
for(int j=0; j<dim2; j++){
mass[j] = 0;
}
}
}
matrix::matrix(const matrix &m){
dim1 = m.dim1;
dim2 = m.dim2;
mass = new double* [dim1];
for (int i=0; i<dim1; i++){
mass = new double[dim2];
}
for(i = 0; i<dim1; i++){
for(int j=0; j<dim2; j++){
mass[j] = m.mass[j];
}
}
}
matrix::~matrix(){
for(int i=0; i<dim1; i++) delete mass;
delete [] mass;
}
template <class T> class Node {
public:
T* object;
Node <T> *next;
Node <T> *prev;
Node();
Node(const Node &);
Node(T);
};
template <class T> Node<T>::Node(){
object = 0;
next = 0;
prev = 0;
}
template <class T> Node<T>::Node(const Node &n){
object = n.object;
next = n.next;
prev = n.prev;
}
template <class T> Node<T>::Node(T obj){
object = &obj;
next = this;
prev = this;
}
template <class T> class List{
public:
Node <T> *n;
Node <T> *curent;
List();
List(Node <T>);
Node <T>* ins(T);
T* del(T);
};
template <class T> List<T>::List(){
Node <T> curent;
Node <T> n;
}
template <class T> List<T>::List(Node<T> node){
Node <T> curent(node);
Node <T> n(node);
}
template <class T> Node <T>* List<T>::ins(T obj){
Node <T> nNode(obj);
List <T> nList(nNode);
if(!nList.curent){
nList.curent = &nNode;
nList.curent->next = &nNode;
nList.curent->prev = &nNode;
}
else{
nList.curent->next = &nNode;
nNode.prev = curent;
}
return curent;
}
void main(){
matrix m(3,3);
List <matrix> list;
list.ins(m);
}
Вот еще одна проблема:
В жирном конструкторе. После того как вызывается конструктор Node <T> nNode(obj); для nNode в нем у свойства остаются определенными поля dim1 И dim2, а адрес первого элемента массива mass теряется.
Так же после вызова конструктора List <T> nList(nNode) теряются адреса
n и current. Что я не правильно делаю ?
object = &obj;
next = this;
prev = this;
}
Всё дело в том, что конструктор получает значение объекта. Соответственно, в поле object оказывается адрес локальной переменной obj, расположенной в стеке программы.
Естественно, когда работа конструктора завершается, производится корректировка стека, и область памяти, на которую указывает object, оказывается свободной. Затем идёт вызов следующей функции, которая перезаписывает её своими данными.
Посему нужно передавать указатель:
{
object = obj;
next = this;
prev = this;
}
Хочу я сделать, как вы уже поняли вот что:
1. есть объект matrix m;
2. есть список List <matrix> list;
3. добавляться m в list должен так: list.insert(m); - добавление в конец списка.
Внутри должно происходить вот что:
а. Для объекта m создается объект класса Node <matrix> nNode (описание его см пред. пост) .
б. nNode добавляется в список.
Но получается то, что каждый раз nNode создается новый и предыдущий узел таким образом убивается. Как быть? Может можно создавать узел для объекта m каждый раз с новым идентификатором и его добавлять в список? Если так, то как это сделать?...И вообще я запутался, подскажите более рациональное решение пожалуйста.
// структура узла
template<typename T>
struct Node
{
T data;
Node<T> *prev, *next;
...
};
// класс списка
template<typename T>
class List
{
// указывают на первый и последний элементы списка
Node<T> *begin, *end;
public:
...
Node<T>* push_back(T);
...
};
template<typename T>
Node<T>* List<T>::push_back(const T& _data)
{
Node<T>* myNode = new Node<T>;
// для своих типов данных, нужно перегрузить оператор присваивания
myNode->data = _data;
// если первый элемент списка
if(begin == NULL)
end = begin = myNode;
else
{
myNode->prev = end;
end->next = myNode;
end = myNode;
}
return myNode;
}
[/FONT]
В общем, классический код, сам такой писал :)
Только небольшая разница
"Node<T>* List<T>::push_back(const T &_data)"
Всё-таки константную ссылку передавать проще, нежели копию объекта, предположительно большого размера.
Нет, метод operator= для структур и классов формируется автоматически.
Нет, метод operator= для структур и классов формируется автоматически.
Хм. А можно поинтересоваться - откуда именно такая информация? Ссылку или описание? В особенности, что касается классов? Я имею ввиду, что нет необходимости его перегружать?
P.S. а на счет перегрузки оператора присваивания по-моему уже где то спорили...
Нет, метод operator= для структур и классов формируется автоматически.
Автоматически просто перегоняется сожержимое полей. А если скажем у тебя одно из полей указатель на выделенную память. Скажем выделенную в конструкторе и освобождаемую в деструкторе. Попробуй догадаться, что будет, если существует два класса с одним и тем же таким указателем?
Только небольшая разница
"Node<T>* List<T>::push_back(const T &_data)"
Всё-таки константную ссылку передавать проще, нежели копию объекта, предположительно большого размера.
Да, чуток не углядел :) пытался доходчиво объяснить, и перестарался.. ;)
А это не про конструктор копирования? Про operator= я, признаюсь, не слышал...
Автоматически формируются 4 метода, которые заполняют данные поэлементно:
- конструктор по-умолчанию
- конструктор копирования
- оператор присваивания
- деструктор (НЕВИРТУАЛЬНЫЙ :eek:)
Посему пока в классе есть только данные (как базовых типов, так и сложных объектов), переопределять дефолтные нужды нет.
А как только появляется поле-указатель.......
Автоматически формируются 4 метода, которые заполняют данные поэлементно:
- конструктор по-умолчанию
- конструктор копирования
- оператор присваивания
- деструктор (НЕВИРТУАЛЬНЫЙ :eek:)
Посему пока в классе есть только данные (как базовых типов, так и сложных объектов), переопределять дефолтные нужды нет.
А как только появляется поле-указатель.......
Уважаемые граждане товарищи. Обращайте внимание на то что вы делаете. Во первых - конструктор по умолчанию генерируется ТОЛЬКО в том случае, если никакой другой конструктор НЕ ОПРЕДЕЛЕН. Второе - всегда и только всегда переопределяйте сами - конструктор копирования, оператор присваивания и деструктор. Вполне верно то что, эти компоненты будут сгенерированы компилятором - но к сожалению только вы знаете - как себя при этом должны вести вести объекты - и только в этом случае вы получите хорошую управляемость. Язык С++ - очень мощный - вы способны делать практически все - поэтому БУДЬТЕ АККУРАТНЫ - лучше потратьте дни на написание, чем недели на поиск непонятной ошибки. Но это ИМХО.