Софтуерно Инженерство
Loading...
marsp avatar marsp 19 Точки

Judge Assignment 04 - Task 05 Lectures

Здравейте!

Макар, че задачата след известна игра я реших, имам няколко въпроса, на които се надявам някой малко да ме просвети за компилационните грешки и причините им, понеже нещо не успях да разбера с ровене в нета. :D 

1. По принцип вкъщи ползвам основно Visual Studio, понеже ми е по-удобен, а на работа понеже имам пролуки свободно време, ползвам CodeBlocks. Преди да превключа на CodeBlocks, единият ми член на класът (итератора, който трябваше да направя) го бях дефинирал така:

std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<namespace::T>>> begin() const

(Държа да отбележа, че до този код стигнах, след като VS в логът с грешките ми изкара, че този тип му трябва, но в момента вече нямам старият код, който изкарваше въпросният лог) И се компилираше нормално, но после като минах на CodeBlocks даваше следната грешка при компилацията:
"error: '_Tree_const_iterator' in namespace 'std' does not name a template type"

При което след "човъркане" подкарах с:

std::Т<Т>::iterator begin() const // нарочно слагам тук "T" за тип, защото все пак е домашно

Това върви и под компилатора на VS. Та въпросът ми е - каква е причината за тази грешка и какво точно значи? 

2. При дефинирането на оператор "[]" доста време ми отне да разбера, защо точно пищи компилатора с грешката:
"error: 'Т& namespace::operator[](namespace::T&)' must be a nonstatic member function" (пак замених с "Т" и "namespace" за да не подсказвам много). Тук основно "nonstatic" частта ме обърква. Под VS дава, че трябва да е просто "member function".

Въпросът ми е - защо специално за този оператор трябва задължително (или поне аз не открих начин) да бъде дефиниран в класът? Оператори "<<", ">>", "<" без проблем можех да ги дефинирам извън класове (приемайки за агрументи въпросният клас и другото нещо, което му трябва, в сравнение само с нещото което му трябва, ако е дефинирано в самият клас) и после да ги пусна като "friend". И разбира се, в крайна сметка коя е по-добрата практика?

Благодаря предварително! И happy coding на всички! :D


Поздрави!

1
C++ Programming
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки
Best Answer

Здравей,

По първия въпрос, когато видиш нещо, което почва с една или две долни черти, това обикновено означава, че е вътрешен клас/обект/нещо за компилатора, тоест нещо, което не е в стандарта, или поне не е предназначено ти да го ползваш. В случая просто ползваш много конкретен итератор - такъв за еди-какъв-си-set (това TreeSet), какъвто Visual Studio си нарича вътрешната имплементация на set класа. Съответно като го дадеш на компилатора на Code::Blocks, то не знае какво е това.

С две думи, питат те "какво ми трябва, за да стигна от Габрово до София" и ти отговаряш "BMW e46, чипосано", вместо да отговориш "превозно средство", и Code::Blocks, понеже има Хонда, се отказва да ходи до София.

begin() в тази ситуация просто трябва да връща същото нещо, което set.begin() връща - std::set<...>::iterator.

По втория въпрос, отговорът не е особено задоволителен - стандартът казва, че operator[] трябва задължително да е член (различните компилатори изкарват различни грешки ако не е, static, когато става въпрос за оператори, означава overload, който не е член, съответно non-static означава, че трябва да е член). Защо е взето това решение не е съвсем ясно, има теории, че причината е да не можеш да го overload-неш за int и да казваш int a = 4; a[4] = 5; макар че чичо Bjarne Stroustrup казва, че просто било "историческа случайност", един вид така са решили някога, после се е оказало, че няма нужда, ама са забравили да го махнат (или нещо такова).

Поздрави,

Жоро

1
marsp avatar marsp 19 Точки

Супер! Now I’ve seen it all! :D Много благодаря за обясненията сенпай Жоро! :)

0