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

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

26.01.2017, 15:06. Показов 1197. Ответов 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
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,176
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
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,176
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
12922 / 6789 / 1818
Регистрация: 18.10.2014
Сообщений: 17,176
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
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru