0 / 0 / 1
Регистрация: 08.10.2013
Сообщений: 21
1

Шаблон, вложенный в него класс и оператор вывода

10.03.2015, 11:04. Показов 1895. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день, делаю учебное задание. надо сделать шаблон стека с использованием односвязного списка. Сделал вот такую функцию:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
template<typename T>
class MyStack2
{
    class Node1
    {
        Node1* pNext;
        T* dataPtr;
 
                //Конструктор, Деструктор
        Node1(const T& sourse, Node1* NextElem);                                                                        
        ~Node1();                                                                                                       
        
        //Перегрузка операторов
        template<typename T> friend std::ostream& operator<< (std::ostream& os, const MyStack2<T>::Node1 sourse);
 
        //Друзья
        friend class MyStack2<T>;
        template<typename T> friend std::ostream& operator<< (std::ostream& os, const MyStack2<T> &sourse);             //вывод списка, тут используем, т.к. нам нужно использовать данные класса Node1
    };
 
    Node1* head;                    //указатель на первый член нашего списка
    int counter;                        //счетчик, сколько всего элементов в стеке
 
public:
 
        //Конструктор, Деструктор
    MyStack2();                 //создание стека конктретных элементов
    ~MyStack2();                    //Деструктор
 
    void push(const T& sourse);         //Положить в стек. создаетсЯ копиЯ объекта
    T pop(void);                    //Возвращает копию объекта, сам объект удаляется
 
    //Перегрузка операторов
    template<typename T> friend std::ostream& operator<< (std::ostream& os, const MyStack2<T> &sourse);             //Оператор вывода
};
 
template<typename T> std::ostream& operator<<(std::ostream& os, const MyStack2<T> &sourse)
{
    MyStack2<T>::Node1 *tPtr = sourse.head;
    while (tPtr != nullptr)
    {
        std::cout << *tPtr;
        tPtr = tPtr->pNext;
    }
    return os;
}
 
template<typename T> std::ostream& operator<<(std::ostream& os, const MyStack2<T>::Node1& sourse)
{
    os << *sourse.dataPtr;
    return os;
}
Возникла проблема с оператором вывода вложенного класса. Компилятор выдает 2 предупреждения и 4 ошибки.
При объявлении функии:
1) Warning 1 warning C4346: 'MyStack2<T>::Node1' : dependent name is not a type o:\курсы\2-е высшее\объектно-ориентированное часть i\проект\лабораторная 7\лабораторная 7\классы\mystack2.h 18 1 Лабораторная 7
2) Error 3 error C2805: binary 'operator <<' has too few parameters o:\курсы\2-е высшее\объектно-ориентированное часть i\проект\лабораторная 7\лабораторная 7\классы\mystack2.h 18 1 Лабораторная 7
3) Error 2 error C2061: syntax error : identifier 'Node1' o:\курсы\2-е высшее\объектно-ориентированное часть i\проект\лабораторная 7\лабораторная 7\классы\mystack2.h 18 1 Лабораторная 7

и точно такие же ошибки на месте реализации функции.

Как я понимаю проблему он почему-то не воспринимает Node1 как класс. Но до меня не доходит что не так.

В чем тут проблема?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.03.2015, 11:04
Ответы с готовыми решениями:

Шаблон и оператор вывода!
Вот код программы: #include &lt;iostream.h&gt; #pragma hdrstop #pragma argsused const int...

Как использовать перегруженный оператор [ ], если дан не сам класс, а указатель на него?
Это указатель на класс figure *f Это перегрузка оператора void figure::operator (int i) { ...

Перегрузить оператор вывода, чтобы заданный пользовательский класс выводился в файл произвольным образом
Добрый вечер. Помогите, пожалуйста. Есть класс class chelovek { private: string name; string...

Вложенный тернарный оператор
Здравствуйте! Нужно вывести кол-во корней квадратного уравнения в зависимости от дискриминанта,...

9
Модератор
Эксперт С++
13498 / 10752 / 6407
Регистрация: 18.12.2011
Сообщений: 28,692
10.03.2015, 11:10 2
Лучший ответ Сообщение было отмечено Lodos как решение

Решение

C++
1
2
3
4
5
6
template<typename T>
class MyStack2
{
    template<typename T2> // нужна другая переменная типа.
    class Node1
    {
Но я бы вынес наружу с предварительным объявлением
C++
1
2
3
4
5
6
7
8
template<typename T> class MyStack2;
template<typename T> 
class Node1
{...};
template<typename T>
class MyStack2
{
  ...
1
0 / 0 / 1
Регистрация: 08.10.2013
Сообщений: 21
10.03.2015, 12:39  [ТС] 3
Если вынести класс наружу, то все у меня получилось. Спасибо!
Т.к. это учебное задание, хотелось бы попробовать сделать и не вынося класс. Как в вашем первом варианте, не вынося класс, вы бы объявили оператор вывода?
Я попробовал сделать так:
C++
1
template<typename T> friend std::ostream& operator<<(std::ostream& os, const MyStack2<T>::Node1<T>::Node1<T> &sourse);
но все равно у меня выдаются те же ошибки + на месте реализации функции:
4) Error 5 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int o:\курсы\2-е высшее\объектно-ориентированное часть i\проект\лабораторная 7\лабораторная 7\классы\mystack2.h 118 1 Лабораторная 7
0
Модератор
Эксперт С++
13498 / 10752 / 6407
Регистрация: 18.12.2011
Сообщений: 28,692
10.03.2015, 12:44 4
Надо тип не T, а другой, Например, T2
0
0 / 0 / 1
Регистрация: 08.10.2013
Сообщений: 21
10.03.2015, 12:50  [ТС] 5
Вот полный код класса. Я понял, что надо у объявления вложенного класса делать другой тип, но у френд функции по идее своя переменная так??
Вот полный код класса, чтобы было понятно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
template<typename T>
class MyStack2
{
    template<typename T2>
    class Node1
    {
        Node1<T2>* pNext;
        T2* dataPtr;
 
        Node1(const T2& sourse, Node1<T2>* NextElem);                                                                                                   
        ~Node1();                                                                                                                                       
        
        //Перегрузка операторов
        template<typename T> friend std::ostream& operator<<(std::ostream& os, const MyStack2<T>::Node1<T>::Node1<T> &sourse);                          //вывод данных страницы
 
        //Друзья
        friend class MyStack2<T2>;
        template<typename T> friend std::ostream& operator<< (std::ostream& os, const MyStack2<T> &sourse);                                             //вывод списка, тут используем, т.к. нам нужно получать данные класса Node1
    };
 
    Node1<T>* head;                     //указатель на первый член нашего списка
    int counter;                        //счетчик, сколько всего элементов в стеке
 
public:
 
    MyStack2();                     
    ~MyStack2();                        
 
    void push(const T& sourse);         //Положить в стек. создаетсЯ копиЯ объекта
    T pop(void);                        //Возвращает копию объекта, сам объект удаляется
 
    //Перегрузка операторов
    template<typename T> friend std::ostream& operator<< (std::ostream& os, const MyStack2<T> &sourse);             //Оператор вывода
};
Как бы вы написали объявление на строке 14? Просто хочу уяснить для себя, как при шаблоне, вложенном в шаблон докричаться до элемента вложенного класса?
0
Модератор
Эксперт С++
13498 / 10752 / 6407
Регистрация: 18.12.2011
Сообщений: 28,692
10.03.2015, 12:58 6
C++
1
 template<typename T2> friend std::ostream& operator<<(std::ostream& os, const MyStack2<T2>::Node1<T2>::Node1<T2> &sourse);
0
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
10.03.2015, 13:03 7
Вообщем, если я правильно понял, вариант 1:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
template <typename T> class Vector;
 
template <typename T>
std::ostream & operator << (std::ostream &os, const Vector<T> &);
 
template <typename T>
class Vector
{
private:
    T * data;
    int size;
public:
    Vector(int);
    ~Vector() { delete[] data; }
    friend std::ostream& operator << <T>(std::ostream& os, const Vector<T> &v);
};
 
template <typename T>
Vector<T>::Vector(int n)
{
    size = n;
    data = new T[size];
    for (int i = 0; i < size; i++)
        data[i] = i;
}
 
template <typename T>
std::ostream & operator << (std::ostream &os, const Vector<T> &V)
{
    for (int i = 0; i < V.size; i++)
        os << V.data[i];
    return os;
}
 
int main()
{
    Vector<int> a(5);
    std::cout << "A: " << a << std::endl;
}
Вариант 2:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
template <typename T>
class Vector
{
private:
    T * data;
    int size;
public:
    Vector(int);
    ~Vector() { delete[] data; }
 
    // Implementation must be out of class!!!!
    template <typename U>
    friend std::ostream& operator <<(std::ostream &, const Vector<U> &);
};
 
template <typename T>
Vector<T>::Vector(int n)
{
    size = n;
    data = new T[size];
    for (int i = 0; i < size; i++)
        data[i] = i;
}
 
template <typename U>
std::ostream& operator <<(std::ostream &os, const Vector<U> &v) {
   for (int i = 0; i < v.size; i++)
       os << v.data[i];
   return os;
}
 
int main()
{
    Vector<int> a(5);
    std::cout << "A: " << a << std::endl;
}
0
0 / 0 / 1
Регистрация: 08.10.2013
Сообщений: 21
10.03.2015, 13:37  [ТС] 8
немного не то. Вопрос был про то, как отправить в функцию вывода класс, вложенный в шаблон, вы же просто 2 способами прописываете френд функцию, насколько я понимаю.
У меня возникает ошибка в том, что он не воспринимает 2-й параметр как тип:
Цитата Сообщение от Lodos Посмотреть сообщение
1) Warning 1 warning C4346: 'MyStack2<T>::Node1' : dependent name is not a type o:\курсы\2-е высшее\объектно-ориентированное часть i\проект\лабораторная 7\лабораторная 7\классы\mystack2.h 18 1 Лабораторная 7
Собственно если вынести класс Node1 как отдельный не вложенный класс, то все становится просто, а вот что делать есть его не выносить?

Добавлено через 3 минуты
Цитата Сообщение от zss Посмотреть сообщение
Код C++
1
2
*template<typename T2> friend std::ostream& operator<<(std::ostream& os, const MyStack2<T2>::Node1<T2>::Node1<T2> &sourse);

Да с этим все понятно, но ситуации это не поменяло. У меня компилятор как не хотел воспринимать "MyStack2<T2>::Node1<T2>::Node1<T2>" как тип объекта так и не хочет. Просто я скорее всего где то ошибся в объявлении этого класса.
И в обще, походу вставлять шаблон в шаблон плохая идея. Сразу как то муторно становится все это использовать.
Ладно пока оставлю этот вопрос, буду делать вынося класс.
0
Модератор
Эксперт С++
13498 / 10752 / 6407
Регистрация: 18.12.2011
Сообщений: 28,692
10.03.2015, 13:58 9
Для Node1 Тоже надо другой тип

operator<<std::ostream& os, const Node1<T2>& sourse)
не описать вне кода, т.к. класс Node1 локальный
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
template<typename T>
class MyStack2
{
    template<typename T3>
    class Node1
    {
        Node1* pNext;
        T3* dataPtr;
 
                //Конструктор, Деструктор
        Node1(const T3& sourse, Node1* NextElem);                                                                        
        ~Node1();                                                                                                       
        
        //Перегрузка операторов
        template<typename T2> 
        friend std::ostream& operator<< (std::ostream& os, const Node1<T2>& sourse)
        {
            os << *sourse.dataPtr;
            return os;
        }
        //Друзья
        friend class MyStack2<T>;
        template<typename T2> friend std::ostream& operator<< (std::ostream& os, const MyStack2<T2> &sourse);             //вывод списка, тут используем, т.к. нам нужно использовать данные класса Node1
    };
 
    Node1<T>* head;                    //указатель на первый член нашего списка
    int counter;                        //счетчик, сколько всего элементов в стеке
 
public:
 
        //Конструктор, Деструктор
    MyStack2();                 //создание стека конктретных элементов
    ~MyStack2();                    //Деструктор
 
    void push(const T& sourse);         //Положить в стек. создаетсЯ копиЯ объекта
    T pop(void);                    //Возвращает копию объекта, сам объект удаляется
 
    //Перегрузка операторов
    template<typename T> friend std::ostream& operator<< (std::ostream& os, const MyStack2<T> &sourse);             //Оператор вывода
};
 
 
template<typename T> std::ostream& operator<<(std::ostream& os, const MyStack2<T> &sourse)
{
    MyStack2<T>::Node1 *tPtr = sourse.head;
    while (tPtr != nullptr)
    {
        std::cout << *tPtr;
        tPtr = tPtr->pNext;
    }
    return os;
}
1
0 / 0 / 1
Регистрация: 08.10.2013
Сообщений: 21
10.03.2015, 14:37  [ТС] 10
Спасибо! Это решило проблему.
0
10.03.2015, 14:37
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.03.2015, 14:37
Помогаю со студенческими работами здесь

Условный оператор, оператор ввода/вывода; плоскость и принадлежность точки
Здравствуйте. В С++ я абсолютный новичок, поэтому с первым же заданием возникли определённые...

Есть класс A и класс B, класс B вложен в класс A и вложен в него, как классу B получить доступ к переменным класса A просто по имени?
На самом деле ничё фантастического я не прошу, ведь: template &lt;class T&gt; class matrix { ...

Может ли объемлющий класс иметь неограниченный доступ к элементам вложенного класса? А вложенный класс — к элементам объемлющего?
Ответ как бы знаю(нет , да). но наверное я что-то не так понимаю, т.к. примерчик написать не...

вложенный класс
Привет всем! создал класс и в этом классе создал еще класс... и я хочу использовать члены внешнего...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru