С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86

Использование вложенного класса

26.01.2017, 15:06. Показов 1208. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Решил подтянуть знания в базовых алгоритмах и структурах данных, а заодно попрактиковаться в шаблонах и обобщенном программировании. Сейчас пишу аналог вектора, и возникли трудности с определениями операций сложения и вычитания итераторов с целыми числами. Вот определение классов:
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
53
54
55
56
57
58
59
60
61
62
template<typename Item>
class MyArrayList
{
    Item * items_;
    int size_;
    int capacity_;
    void GrowArray();
public:
    class iterator
    {
        const MyArrayList<Item> * ptr_;
        int index_;
        iterator(const MyArrayList<Item> * ptr, int index)
            : ptr_(ptr), index_(index) {}
        friend iterator MyArrayList<Item>::begin() const;
        friend iterator MyArrayList<Item>::end() const;
        friend iterator MyArrayList<Item>::rbegin() const;
        friend iterator MyArrayList<Item>::rend() const;
    public:
        iterator()
            : ptr_(nullptr), index_(-1) {}
        void operator++() 
        { ptr_ != nullptr && index_ < ptr_->size_ ? ++index_ : throw std::logic_error("iterator not incrementable"); }
        void operator++(int)
        { operator++(); }
        void operator--() 
        { ptr_ != nullptr && index_ > 0  ? --index_ : throw std::logic_error("iterator not decrementable"); }
        void operator--(int)
        { operator--(); }
        iterator & operator+(const int val);
        iterator & operator-(const int val);
        friend iterator & operator+(const int val, const iterator & iter);
        bool operator==(const iterator & other) const;
        bool operator!=(const iterator & other) const
        { return !operator==(other); }
        Item & operator*() const;
    };
    explicit MyArrayList(const int lenght = 0);
    MyArrayList(const MyArrayList<Item> & other);
    MyArrayList<Item> & operator=(const MyArrayList<Item> & other);
    ~MyArrayList() { delete[] items_; }
    void reserve(const int size);
    Item & at(const int index) const;
    int indexOf(const Item & item) const;
    void insert(const int index, const Item & item);
    void removeAt(const int index);
    void push_back(const Item & item);
    void pop_back();
    void clear();
    void copyTo(Item arr[], int arrIndex) const;
    void swap(MyArrayList<Item> & other);
    bool remove(const Item & item);
    bool contains(const Item & item) const;
    int size() const { return size_; }
    int capacity() const { return capacity_; }
    bool empty() const { return size_ == 0; }
    Item & operator[](const int index) const;
    iterator begin() const { return iterator::iterator(this, 0);  }
    iterator rbegin() const { return iterator(this, size_ - 1); }
    iterator end() const { return iterator(this, size_); }
    iterator rend() const { return iterator(this, -1); }
};
При попытке определить метод сложения таким образом:
C++
1
2
3
4
5
template<typename Item>
iterator & MyArrayList<Item>::iterator::operator+(const int val)
{
    // TODO: insert return statement here
}
компилятор выдает ряд ошибок , из которых ключевой мне кажется "unrecognizable template declaration/definition". Если правильно понимаю, до уточнения метода operator+ компилятор не понимает что такое iterator, т.к. класс имеет область видимости класса MyArrayList.
Я попробовал использовать предопределение класса iterator до определения метода:
C++
1
class iterator;
...но теперь выдает "MyArrayList<Item>::iterator::operat or +': unable to match function definition to an existing declaration"
Пробовал что-то такое:
C++
1
2
3
4
5
auto MyArrayList<Item>::iterator::operator-(const int val)->decltype(*this)
{
    
    return *this;
}
...но в том месте this использовать нельзя, да и вообще странная идея была.
Подскажите, как это сделать правильно?

Добавлено через 4 часа 42 минуты
Так, кстати, тоже нельзя:
C++
1
2
3
4
5
template<typename Item>
MyArrayList<Item>::iterator & MyArrayList<Item>::iterator::operator+(const int val)
{
    // TODO: insert return statement here
}
Неужели никто не подскажет? Это же должно быть очень просто
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.01.2017, 15:06
Ответы с готовыми решениями:

Как вынести описание методов вложенного класса за пределы класса?
Подскажите, пожалуйста, как мне вынести описание методов вложенного класса за пределы класса?

В конструкторе вложенного класса инициализируется приватное поле. Потом вызывается функция-метод этого класса и выводит значение этого поля НО НЕ ТО!
Друзья! Почему так? #include &lt;windows.h&gt; #include &lt;iostream&gt; using namespace std; //Вот главный класс class A{ ...

Вызов метода вложенного класса
class player { public: void showHp() { cout &lt;&lt;&quot;Health: &quot;&lt;&lt; hp&lt;&lt;endl; } void showInvetory() ...

17
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
26.01.2017, 15:12
Цитата Сообщение от 4elovek37 Посмотреть сообщение
Так, кстати, тоже нельзя:
Нужно так:
C++
1
2
3
4
5
template<typename Item>
typename MyArrayList<Item>::iterator & MyArrayList<Item>::iterator::operator+(const int val)
{
    // TODO: insert return statement here
}
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.01.2017, 15:14
Цитата Сообщение от DrOffset Посмотреть сообщение
Нужно так:
эм...

вообще то вот так:
C++
1
2
3
4
5
template<typename Item>
auto MyArrayList<Item>::iterator::operator+(const int val)   //<--- убрал ссылку
{
    // TODO: insert return statement here
}
это же не +=
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
26.01.2017, 15:16
Цитата Сообщение от hoggy Посмотреть сообщение
эм...
Я про typename.
А ссылку там и правда не надо возвращать.
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
26.01.2017, 15:38
Цитата Сообщение от 4elovek37 Посмотреть сообщение
компилятор выдает ряд ошибок , из которых ключевой мне кажется "unrecognizable template declaration/definition".
Компилятор не может вывести тип шаблона. Нужно подсказать ему с помощью typename, либо позволить выводить тип с помощью ключевого слова auto (C++14, можно извернуться с decltype для С++11, но думаю не стоит).
0
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
26.01.2017, 16:46  [ТС]
С использованием typename компилируется, спасибо!
Цитата Сообщение от MrGluck Посмотреть сообщение
Компилятор не может вывести тип шаблона. Нужно подсказать ему с помощью typename
Впервые вижу такой прием. У этого есть какое-нибудь название, что бы нагуглить-почитать? А почему не может вывести? Я полагал что дело тут в области видимости.
Цитата Сообщение от DrOffset Посмотреть сообщение
А ссылку там и правда не надо возвращать.
Верно, это я на автомате написал, правильно будет возвращать по значению
C++
1
2
3
4
5
template<typename Item>
typename MyArrayList<Item>::iterator MyArrayList<Item>::iterator::operator+(const int val)
{
    // TODO: insert return statement here
}
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
26.01.2017, 16:57
4elovek37, для полного просветления советую почитать книгу "Шаблоны C++. Справочник разработчика", раздел про "Зависимые имена шаблонов".

Добавлено через 47 секунд
Для старта можно еще вот это почитать: https://msdn.microsoft.com/ru-... zs2ee.aspx
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
26.01.2017, 17:00
Цитата Сообщение от 4elovek37 Посмотреть сообщение
У этого есть какое-нибудь название, что бы нагуглить-почитать?
Template deduction.
С помощью typename мы явно говорим, что используется тип данных, иначе, компилятор воспринимает это как статическую переменную, объявленную в классе. Ничто ведь не мешает нам создать статическую переменную iterator в классе MyArrayList

Добавлено через 23 секунды
https://blogs.msdn.microsoft.c... arameters/
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.01.2017, 19:02
Цитата Сообщение от 4elovek37 Посмотреть сообщение
У этого есть какое-нибудь название, что бы нагуглить-почитать?
Алёнушка годно объясняет:
http://alenacpp.blogspot.ru/2006/08/typename.html
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12930 / 6798 / 1820
Регистрация: 18.10.2014
Сообщений: 17,208
26.01.2017, 20:03
Цитата Сообщение от MrGluck Посмотреть сообщение
Template deduction.
С помощью typename мы явно говорим, что используется тип данных, иначе, компилятор воспринимает это как статическую переменную, объявленную в классе. Ничто ведь не мешает нам создать статическую переменную iterator в классе MyArrayList
Все правильно, но к какому-то "template deduction" это никакого отношения не имеет. Даже непонятно, что такое "template deduction".

Также "статические переменные" тут ни при чем. Да и почему именно статические?

-----------------------

Цитата Сообщение от 4elovek37 Посмотреть сообщение
Пробовал что-то такое:
C++
1
2
3
4
auto MyArrayList<Item>::iterator::operator-(const int val)->decltype(*this)
{
    return *this;
}
...но в том месте this использовать нельзя, да и вообще странная идея была.
Подскажите, как это сделать правильно?
"Странная"? Наоборот, все правильно. Ваш оригинальный вариант в этом формате правильно записывается как просто

C++
1
2
3
4
5
template<typename Item>
auto MyArrayList<Item>::iterator::operator+(const int val) -> iterator
{
  ...
}
учитывая, как уже было правильно сказано, что ссылка там ни к чему.

decltype(*this) тоже должно было прекрасно работать, с той только разницей, что decltype(*this) - ссылка, а вам там ссылка не нужна. Пришлось бы делать std::remove_reference<decltype(*this)>::type.
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
26.01.2017, 20:08
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
непонятно, что такое "template deduction"
Вывод типа шаблона. Без typename шаблон не может вывести тип, ему нужна подсказка.
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Да и почему именно статические?
Потому что именно они соответствуют синтаксису
Цитата Сообщение от 4elovek37 Посмотреть сообщение
MyArrayList<Item>::iterator
То есть это похоже на обращение к статической переменной iterator шаблонного класса MyArrayList с типом Item.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using Item = int;
 
template <typename T>
class MyArrayList
{
public:
    static int iterator;
};
 
template <>
int MyArrayList<Item>::iterator = 1;
 
int main()
{
    std::cout << MyArrayList<Item>::iterator;
}
Глупо, но с точки зрения парсера именно так.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12930 / 6798 / 1820
Регистрация: 18.10.2014
Сообщений: 17,208
26.01.2017, 20:13
Цитата Сообщение от MrGluck Посмотреть сообщение
Вывод типа шаблона. Без typename шаблон не может вывести тип, ему нужна подсказка.
Термин "deduction" в С++ в этом контексте никогда не употреблялся. До появления auto термин deduction использовался только в template argument deduction для шаблонов функций. К этой ситуации никакого отношения не имеет даже отдаленно.

Цитата Сообщение от MrGluck Посмотреть сообщение
Потому что именно они соответствуют синтаксису
Синтаксису? А, скажем, нестатические переменные чем не соответствуют данному синтаксису? А члены внутреннего enum чем не соответствуют данному синтаксису?
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
26.01.2017, 20:34
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
в этом контексте никогда не употреблялся
Как тогда правильно звучит "вывод типа шаблона"?
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
А, скажем, нестатические переменные чем не соответствуют синтаксису?
К ним нельзя обратиться с тем же синтаксисом, что я указал выше. А именно
Цитата Сообщение от MrGluck Посмотреть сообщение
MyArrayList<Item>::iterator
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12930 / 6798 / 1820
Регистрация: 18.10.2014
Сообщений: 17,208
26.01.2017, 20:41
Цитата Сообщение от MrGluck Посмотреть сообщение
Как тогда правильно звучит "вывод типа шаблона"?
Приведите пример. Что такое "вывод типа шаблона"?

Цитата Сообщение от MrGluck Посмотреть сообщение
К ним нельзя обратиться с тем же синтаксисом, что я указал выше. А именно
Это как это нельзя? Пожалуйста

C++
1
2
3
4
5
6
7
8
9
struct A { 
  int i; 
 
  void foo() {
    A::i = 5; // <- вот он!
  }
 
  int A::*p = &A::i; // <- вот он снова!
};
Синтаксис ClassName::MemberName - это квалифицированное имя члена класса - один из фундаментальнейших синтаксисов С++. Он применим к абсолютно любым членам класса, без исключения.

Другое дело, что возможность обращаться к членам разного вида (через любой синтаксис) зависит от окружающего контекста, но это уже к данному синтаксису отношения не имеет.
2
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
26.01.2017, 21:10
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Приведите пример. Что такое "вывод типа шаблона"?
Всё же для C++17 помимо template argument deduction появился термин class template deduction (http://en.cppreference.com/w/c... _deduction). Или он же Template argument deduction for class templates (http://www.open-std.org/jtc1/s... 091r3.html)
Но я признаю, что обе эти возможности не имеют отношения к данной ситуации. Что-то увидел шаблоны и меня приглючило. Спасибо, что поправили.

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Это как это нельзя? Пожалуйста
Согласен, тут важен контекст. А так, чтобы можно было обратиться вне класса и его методов?
0
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
27.01.2017, 10:14  [ТС]
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
"Странная"? Наоборот, все правильно. Ваш оригинальный вариант в этом формате правильно записывается как просто
C++
1
2
template<typename Item>
auto MyArrayList<Item>::iterator::operator+(const int val) -> iterator
Да, так тоже работает. Все-таки я был близок. Хотя как-то подсознательно стараюсь избегать использования auto где-либо.
Что бы не плодить топики (да и по теме подходит), спрошу здесь же:
А как правильно поступить с friend op+ функцией? По идее, делать её шаблонной нет необходимости - независимо от конкретной специализации она всегда будет вызывать op+ класса итератора, расставляя операнды в "правильном" порядке. Но мне кажется, что сделать её нешаблонной не получится, или я ошибаюсь?
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
27.01.2017, 10:34
del
0
5 / 5 / 0
Регистрация: 10.10.2014
Сообщений: 86
27.01.2017, 13:56  [ТС]
С дружественной функцией пока пришел только к этому:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template<typename Item>
class MyArrayList
{
    //...
        public:
    class iterator
    {
        //...
    public:
        //...
        iterator operator+(const int val) const;
        iterator operator-(const int val) const;
        friend iterator operator+(const int val, const iterator & iter)
        { return iter + val; }
        //...
    };
    //...
};
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.01.2017, 13:56
Помогаю со студенческими работами здесь

Не видит поля вложенного класса
Создаю свою реализацию stl::list. Также есть электронное пособие с учебного заведения, где уже реализован list, не до конца,а в качестве...

Вектор типа вложенного класса
Здравствуйте. Я делаю свой список. Для этого я создала вложенные классы (List -- мой список, его элементы -- объекты класса типа Elem....

Объявление объекта вложенного класса
Есть структура наподобие: template&lt;class T&gt; class A{ //...... public: class B { int dd; int mm; int yy; ...

Описать конструктор вложенного класса
Привет всем! пожалуйста объясните как правильно описать конструктор вложенного класса в .cpp и доступ к переменной (чтобы присвоить...

Реализация методов вложенного класса
Здравствуйте, необходимо реализовать внешний и вложенный закрытый класс, прим.: A.h class A:{ class B:{ int C, D; ...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Old Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru