Russian Qt Forum

Программирование => С/C++ => Тема начата: Pupil от Сентябрь 24, 2014, 12:05



Название: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 24, 2014, 12:05
Здравствуйте!

Набранный пример из книги 1 в 1 не заработал. Подправил всё, что смог. Осталось 2-е ошибки:

1. main.cpp:73: ошибка: expected constructor, destructor, or type conversion before '*' token

2. main.cpp:85: ошибка: expected constructor, destructor, or type conversion before '*' token

 Прошу кратко описать логику исправления и не пороть строго ученика. Спасибо!

Код:
#include <QtCore/QCoreApplication>
#include <iostream>

template <class Data> class List{
    class Node{
        public:
            Data d;
            Node *next, *prev;
            Node(Data dat = 0){d = dat; next = 0; prev = 0;}
    };

    Node *pbeg, *pend;
        public:
        List(){pbeg = 0; pend = 0;}
        ~List();
    void add(Data d);
    Node * find(Data i);
    Node * insert(Data key, Data d);
    bool remove(Data key);
    void print();
    void print_back();
};



//-------------------------------------
template <class Data>
List <Data>::~List(){
if (pbeg !=0){
Node *pv = pbeg;
while (pv){
pv = pv->next; delete pbeg;
pbeg = pv;}
    }
}

//-------------------------------------

template <class Data>
void List <Data>::print(){
Node *pv = pbeg;
std::cout << std::endl << "list: ";
while (pv){
std::cout << pv->d << ' ';
pv = pv->next;}
std::cout << std::endl;
}

//-------------------------------------

template <class Data>
void List <Data>::print_back(){
Node *pv = pend;
std::cout << std::endl << " list back: ";
while (pv){
std::cout << pv->d << ' ';
pv = pv->prev;}
std::cout << std::endl;
}

//-------------------------------------

template <class Data>
void List <Data>::add(Data d){
Node *pv = new Node(d);
if (pbeg == 0)pbeg = pend = pv;
else{
pv->prev = pend;
pend->next = pv;
pend = pv;}
}

//-------------------------------------

template <class Data>
Node * List <Data>::find(Data d){
Node *pv = pbeg;
while (pv){
if(pv->d == d)break;
pv = pv->next;
}
return pv;
}

//------------------------------------

template <class Data>
Node * List<Data>::insert(Data key, Data d){
if(Node *pkey = find(key)){
Node *pv = new Node(d);
pv->next = pkey->next;

pv->prev = pkey;
pkey->next =* pv;
if (pkey != pend)(pv->next)->prev = pv;
else pend = pv;
return pv;}
return 0;
}

template <class Data>
bool List <Data>::remove(Data key){
    if(Node *pkey = find(key)){
        if (pkey == pbeg){
        pbeg = pbeg->next; pbeg->prev = 0;}
        else if(pkey == pend){
        pend = pend->prev; pend->next = 0;}
    else {
         (pkey->prev)->next = pkey->next;
         (pkey->next)->prev = pkey->prev;}
         delete pkey; return true;}
         return false;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
   
    return a.exec();
}


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: m_ax от Сентябрь 24, 2014, 12:24
Код
C++ (Qt)
template <class Data>
Node * List <Data>::find(Data d)
 
нужно исправить на
Код
C++ (Qt)
template <class Data>
typename List<Data>::Node * List <Data>::find(Data d)
 

И аналогично с методом insert..


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: OKTA от Сентябрь 24, 2014, 12:29
m_ax, объясни пожалуйста, в чем тут засада? Из-за приватности Node и того, что компилятор не понимает, что Node это какой-то тип?


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: m_ax от Сентябрь 24, 2014, 12:36
m_ax, объясни пожалуйста, в чем тут засада? Из-за приватности Node и того, что компилятор не понимает, что Node это какой-то тип?
Из-за того, что компилятор не понимает что возвращаемый тип Node - это именно тот самый ноде)
А  typename нужен для того, чтобы явно сказать компилятору, что Node это тип (поскольку List шаблонный класс)..
   


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: OKTA от Сентябрь 24, 2014, 12:41
Спасибо!  8)


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 24, 2014, 12:46
m_ax, Спасибо!!! Я понял, что компилятор не понимает возвращаемый тип ввиду того, что в редакторе кода шрифт Node серого цвета, а не активного.
Спасибо!


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 24, 2014, 14:20
У меня снова текут слёзы. Классы скомпилировались, а вызвать функции из main не получается. Ругается...

После объявления класса написал:

Код:
typedef List<class Data> lst;

В функции main:

Код:
  lst lst1;
    for(int i = 0; i < 8; ++i) lst1::add(i);

компилятор выдает ошибку:

main.cpp:124: ошибка: 'lst1' is not a class or namespace


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Old от Сентябрь 24, 2014, 14:22
У меня снова текут слёзы.
Пока вы не изучите c++ они будут течь постоянно. ;)

Код:
  lst lst1;
    for(int i = 0; i < 8; ++i) lst1.add(i);


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 24, 2014, 14:31
Спасибо, Учитель. Но через доступ не :: , . компилятор также выдает ошибку:

main.cpp:124: ошибка: no matching function for call to 'List<Data>::add(int&)'


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: OKTA от Сентябрь 24, 2014, 14:34
А разве вообще разрешено вот так просто тэмплэйт впихивать в typedef?


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Old от Сентябрь 24, 2014, 14:35
Спасибо, Учитель. Но через доступ не :: , . компилятор также выдает ошибку:

main.cpp:124: ошибка: no matching function for call to 'List<Data>::add(int&)'
Ну так это совсем другая ошибка. :)
Если вы хотите хранить в вашем списке инты, то и указывать это нужно явно:
Код
C++ (Qt)
typedef List<int> lst;
 


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Igors от Сентябрь 24, 2014, 14:36
А  typename нужен для того, чтобы явно сказать компилятору, что Node это тип (поскольку List шаблонный класс)..
А в "самом строгом" компиляторе (по Верес'у) можно без typename. Правда потом, при переносе кода на OSX, приходится лупать глазами...

А вот что плохого в этой реализации (как я понял из книжки)? Или все хорошо?  :)


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Old от Сентябрь 24, 2014, 14:37
А разве вообще разрешено вот так просто тэмплэйт впихивать в typedef?
Конечно, когда наугад пытаешься писать. :)


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 24, 2014, 14:43
Я правильно понял, что использовании класса template необходимо в объявлении экземпляра явно указывать тип переменной, чтобы уйти от абстракции типа Data?
Пример сам по себе хороший - в теоретической части -том 1 - он неполный... )


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: OKTA от Сентябрь 24, 2014, 14:50
А разве вообще разрешено вот так просто тэмплэйт впихивать в typedef?
Конечно, когда наугад пытаешься писать. :)

Хм, на сколько я знаю, делать шаблонные typedef типа typedef List<class Data> lst можно по-человечески только в c++11 через using, а до этого приходилось придумывать всякие конструкции в обход. Или я что-то путаю?


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 24, 2014, 14:53
Я учусь и не уразумею. Сейчас пролучилось без typedef )
Спасибо!


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: m_ax от Сентябрь 24, 2014, 16:01
А вот что плохого в этой реализации (как я понял из книжки)? Или все хорошо?  :)
Со стандартными алгоритмами его не попользуешь)
А вообще, подобные примеры не стоит воспринимать всерьёз, поскольку у них немного другое предназначение)


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Igors от Сентябрь 24, 2014, 16:36
Со стандартными алгоритмами его не попользуешь)
Да, итератров не видно. Но мне совсем др минус бросился в глаза


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 29, 2014, 15:54
Какой минус- можно узнать? )


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Igors от Сентябрь 29, 2014, 16:25
Какой минус- можно узнать? )
Нет кеша, new/delete вызывается на каждый чих. Конечно от учебного примера это не требуется, но если надо будет выжимать скорость - такой список будет притормаживать.


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 29, 2014, 18:40
А есть где такой пример-учебный- только правильный и оптимизированный? )


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Igors от Сентябрь 30, 2014, 09:16
А есть где такой пример-учебный- только правильный и оптимизированный? )
1) учебный 2) правильный 3) оптимизированный
Можно выбрать только 2 из 3  :)

Если "правильный и оптимизированный" - то стандартный std::list. Исходники есть, можно пройти по шагам в отладчике gdb или MSVC. Правда мало не покажется, текст там очень уродлив, понять его трудно.


Название: Re: Пример из Павловской. Шаблон класса.
Отправлено: Pupil от Сентябрь 30, 2014, 09:50
Igors, Спасибо!