Russian Qt Forum
Ноябрь 27, 2024, 00:17 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Пример из Павловской. Шаблон класса.  (Прочитано 9276 раз)
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();
}
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #1 : Сентябрь 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..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
OKTA
Гость
« Ответ #2 : Сентябрь 24, 2014, 12:29 »

m_ax, объясни пожалуйста, в чем тут засада? Из-за приватности Node и того, что компилятор не понимает, что Node это какой-то тип?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #3 : Сентябрь 24, 2014, 12:36 »

m_ax, объясни пожалуйста, в чем тут засада? Из-за приватности Node и того, что компилятор не понимает, что Node это какой-то тип?
Из-за того, что компилятор не понимает что возвращаемый тип Node - это именно тот самый ноде)
А  typename нужен для того, чтобы явно сказать компилятору, что Node это тип (поскольку List шаблонный класс)..
   
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
OKTA
Гость
« Ответ #4 : Сентябрь 24, 2014, 12:41 »

Спасибо!  Крутой
Записан
Pupil
Гость
« Ответ #5 : Сентябрь 24, 2014, 12:46 »

m_ax, Спасибо!!! Я понял, что компилятор не понимает возвращаемый тип ввиду того, что в редакторе кода шрифт Node серого цвета, а не активного.
Спасибо!
Записан
Pupil
Гость
« Ответ #6 : Сентябрь 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
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #7 : Сентябрь 24, 2014, 14:22 »

У меня снова текут слёзы.
Пока вы не изучите c++ они будут течь постоянно. Подмигивающий

Код:
  lst lst1;
    for(int i = 0; i < 8; ++i) lst1.add(i);
Записан
Pupil
Гость
« Ответ #8 : Сентябрь 24, 2014, 14:31 »

Спасибо, Учитель. Но через доступ не :: , . компилятор также выдает ошибку:

main.cpp:124: ошибка: no matching function for call to 'List<Data>::add(int&)'
Записан
OKTA
Гость
« Ответ #9 : Сентябрь 24, 2014, 14:34 »

А разве вообще разрешено вот так просто тэмплэйт впихивать в typedef?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Сентябрь 24, 2014, 14:35 »

Спасибо, Учитель. Но через доступ не :: , . компилятор также выдает ошибку:

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

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Сентябрь 24, 2014, 14:36 »

А  typename нужен для того, чтобы явно сказать компилятору, что Node это тип (поскольку List шаблонный класс)..
А в "самом строгом" компиляторе (по Верес'у) можно без typename. Правда потом, при переносе кода на OSX, приходится лупать глазами...

А вот что плохого в этой реализации (как я понял из книжки)? Или все хорошо?  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #12 : Сентябрь 24, 2014, 14:37 »

А разве вообще разрешено вот так просто тэмплэйт впихивать в typedef?
Конечно, когда наугад пытаешься писать. Улыбающийся
Записан
Pupil
Гость
« Ответ #13 : Сентябрь 24, 2014, 14:43 »

Я правильно понял, что использовании класса template необходимо в объявлении экземпляра явно указывать тип переменной, чтобы уйти от абстракции типа Data?
Пример сам по себе хороший - в теоретической части -том 1 - он неполный... )
Записан
OKTA
Гость
« Ответ #14 : Сентябрь 24, 2014, 14:50 »

А разве вообще разрешено вот так просто тэмплэйт впихивать в typedef?
Конечно, когда наугад пытаешься писать. Улыбающийся

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


Страница сгенерирована за 0.142 секунд. Запросов: 23.