Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Шаблоны

1.9K
23 февраля 2007 года
burst
94 / / 04.09.2006
Делаю шаблон списка. Есть 2 класса: класс Node - узел и класс List собственно список.
Код:
template <class T> class Node {
    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'
Что то я никак не вьеду, что ему не нравится...
505
23 февраля 2007 года
vAC
343 / / 28.02.2006
Класс Node - является шаблоном. List - нет. Поэтому как он поймет, что такое T для него? Сделай List тоже шаблоном, либо в классе List должен использоваться конкретный экземпляр шаблона Node
9
23 февраля 2007 года
Lerkin
3.0K / / 25.03.2003
 
Код:
template <class T> class Node {
    T *object;
public:
    Node<T> *next;
    Node<T> *prev;
    Node();
    Node(T);
};
...

Так, имхо, правильнее будет.

Ну, и List, конечно, шаблонным надо сделать.
1.9K
23 февраля 2007 года
burst
94 / / 04.09.2006
Ок. Вопрос второй. Добавил метод.

Код:
template <class T> T* List<T>::ins(T obj){
    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;
}



 
Код:
void main(){
      matrix m(3,3);
      List <matrix> list();
}

Так вот когда программа выполняется, то выделенная строка вобще как-то игнорируется и отладчик через нее перескакивает, как будто ее нет. И если написать так:
 
Код:
void main(){
    matrix m(3,3);
    List <matrix> list();
    list.ins(m);
}

то выдается ошибка left of '.ins' must have class/struct/union type. тоесть List не является классом ?
505
23 февраля 2007 года
vAC
343 / / 28.02.2006
А скобки-то зачем??? Такой конструкцией описывается прототип функции :)
Попробуй так:
 
Код:
void main(){
      matrix m(3,3);
      List <matrix> list;
}
1.9K
23 февраля 2007 года
burst
94 / / 04.09.2006
Да, облажался. Я думал вызываю конструктор по умолчанию...
1.9K
25 февраля 2007 года
burst
94 / / 04.09.2006
Код:
class matrix {

    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. Что я не правильно делаю ?
309
25 февраля 2007 года
el scorpio
1.1K / / 19.09.2006
Цитата:
template <class T> Node<T>::Node(T obj){
object = &obj;
next = this;
prev = this;
}


Всё дело в том, что конструктор получает значение объекта. Соответственно, в поле object оказывается адрес локальной переменной obj, расположенной в стеке программы.
Естественно, когда работа конструктора завершается, производится корректировка стека, и область памяти, на которую указывает object, оказывается свободной. Затем идёт вызов следующей функции, которая перезаписывает её своими данными.
Посему нужно передавать указатель:

 
Код:
template <class T> Node<T>::Node(T *obj)
{
    object = obj;
    next = this;
    prev = this;
}
1.9K
26 февраля 2007 года
burst
94 / / 04.09.2006
Ппц, я что-то вообще запутался.
Хочу я сделать, как вы уже поняли вот что:
1. есть объект matrix m;
2. есть список List <matrix> list;
3. добавляться m в list должен так: list.insert(m); - добавление в конец списка.
Внутри должно происходить вот что:
а. Для объекта m создается объект класса Node <matrix> nNode (описание его см пред. пост) .
б. nNode добавляется в список.

Но получается то, что каждый раз nNode создается новый и предыдущий узел таким образом убивается. Как быть? Может можно создавать узел для объекта m каждый раз с новым идентификатором и его добавлять в список? Если так, то как это сделать?...И вообще я запутался, подскажите более рациональное решение пожалуйста.
9
26 февраля 2007 года
Lerkin
3.0K / / 25.03.2003
как макет:
Код:
[FONT="Courier New"]
// структура узла
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]
309
26 февраля 2007 года
el scorpio
1.1K / / 19.09.2006
Lerkin
В общем, классический код, сам такой писал :)
Только небольшая разница
"Node<T>* List<T>::push_back(const T &_data)"
Всё-таки константную ссылку передавать проще, нежели копию объекта, предположительно большого размера.
Цитата:
для своих типов данных, нужно перегрузить оператор присваивания


Нет, метод operator= для структур и классов формируется автоматически.

1
26 февраля 2007 года
kot_
7.3K / / 20.01.2000
Цитата: el scorpio

Нет, метод operator= для структур и классов формируется автоматически.


Хм. А можно поинтересоваться - откуда именно такая информация? Ссылку или описание? В особенности, что касается классов? Я имею ввиду, что нет необходимости его перегружать?

1.9K
26 февраля 2007 года
burst
94 / / 04.09.2006
vAC, Lerkin, el scorpio, большое спасибо за помощь!
P.S. а на счет перегрузки оператора присваивания по-моему уже где то спорили...
505
26 февраля 2007 года
vAC
343 / / 28.02.2006
Цитата: el scorpio

Нет, метод operator= для структур и классов формируется автоматически.



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

9
26 февраля 2007 года
Lerkin
3.0K / / 25.03.2003
Цитата: el scorpio
...
Только небольшая разница
"Node<T>* List<T>::push_back(const T &_data)"
Всё-таки константную ссылку передавать проще, нежели копию объекта, предположительно большого размера.


Да, чуток не углядел :) пытался доходчиво объяснить, и перестарался.. ;)

Цитата: el scorpio
Нет, метод operator= для структур и классов формируется автоматически.


А это не про конструктор копирования? Про operator= я, признаюсь, не слышал...

309
27 февраля 2007 года
el scorpio
1.1K / / 19.09.2006
Kot_, Lerkin, vAC
Автоматически формируются 4 метода, которые заполняют данные поэлементно:
- конструктор по-умолчанию
- конструктор копирования
- оператор присваивания
- деструктор (НЕВИРТУАЛЬНЫЙ :eek:)

Посему пока в классе есть только данные (как базовых типов, так и сложных объектов), переопределять дефолтные нужды нет.
А как только появляется поле-указатель.......
1
28 февраля 2007 года
kot_
7.3K / / 20.01.2000
Цитата: el scorpio
Kot_, Lerkin, vAC
Автоматически формируются 4 метода, которые заполняют данные поэлементно:
- конструктор по-умолчанию
- конструктор копирования
- оператор присваивания
- деструктор (НЕВИРТУАЛЬНЫЙ :eek:)

Посему пока в классе есть только данные (как базовых типов, так и сложных объектов), переопределять дефолтные нужды нет.
А как только появляется поле-указатель.......


Уважаемые граждане товарищи. Обращайте внимание на то что вы делаете. Во первых - конструктор по умолчанию генерируется ТОЛЬКО в том случае, если никакой другой конструктор НЕ ОПРЕДЕЛЕН. Второе - всегда и только всегда переопределяйте сами - конструктор копирования, оператор присваивания и деструктор. Вполне верно то что, эти компоненты будут сгенерированы компилятором - но к сожалению только вы знаете - как себя при этом должны вести вести объекты - и только в этом случае вы получите хорошую управляемость. Язык С++ - очень мощный - вы способны делать практически все - поэтому БУДЬТЕ АККУРАТНЫ - лучше потратьте дни на написание, чем недели на поиск непонятной ошибки. Но это ИМХО.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог