//----------- файл TArray.h#include <iostream>
class Array
{ public:
// типы исключений:class bad_Index {}; // индекс вне диапазонаclass bad_Range {}; // если левый адрес > правый адресclass bad_Size {}; // неправильный размер
// типы:typedef double value_type;
typedef double* iterator;
typedef const double* iterator_const;
typedef double& reference;
typedef const double& const_reference;
typedef std::size_t size_type;
// конструкторы/присваивание/деструктор:
Array( size_type size, value_type k = 0.0 );
Array( const Array& array );
Array( iterator_const, iterator_const );
~Array(){ delete[] elems; elems = 0; } // освобождаем память
Array& operator=( const Array& );
size_type size() const { return Size; } // текущий размер массива
// доступ к элементам:
reference operator[]( size_type );
const_reference operator[]( size_type ) const;
reference front() { return elems[0]; } // первый элемент
const_reference front() const { return elems[0]; }
reference back() { return elems[size() - 1]; } // последний элемент
const_reference back() const { return elems[size() - 1]; }
void Swap( Array &other ) // обменять с другим массивом
{ std::swap( elems, other.elems ); // стандартная функция обмена
std::swap( Size, other.Size );
}
friend std::ostream& operator<< (std::ostream &t, const Array &V );
private:
size_type Size; // выделено элементов в памяти
value_type * elems; // указатель на данныеvoid rangecheck ( size_type i ) const
{ if ( i >= size() ) throw bad_Index(); }
};
// ----------------файл TArray.cpp#include"TArray.h"#include <iostream>
Array::Array( size_type size, value_type k )
{ if ( size == 0 ) throw bad_Size(); // генерация исключения
Size = size;
elems = new value_type[Size]; // создали массивfor( size_type i = 0; i < Size; ++i ) // заполняем массив
elems[i] = k; // значение по умолчанию
}
Array::Array( iterator_const begin, iterator_const end )
{ if ( begin >= end ) throw bad_Range(); // генерация исключения
Size = end - begin; // количество элементов
elems = new value_type[Size]; // создаем массив
size_type i = 0;
while( begin != end ) // заполняем массив
elems[i++] = *begin++; // копируем из массива
}
Array::Array( const Array &t )
: Size( t.Size ), elems( new value_type[Size] )
{ for( size_type i = 0; i < Size; ++i ) elems[i] = t.elems[i]; }
Array& Array::operator=( const Array &t )
{ Array temp( t ); // временнный локальный объект temp = t
Swap( temp ); // обмен полями с текущим объектомreturn *this; // возврат нового текущего объекта
} // объект temp уничтоженArray::reference Array::operator[]( size_type index )
{ if ( index < size() ) return elems[index];
else throw bad_Index(); // генерация исключения
}
Array::const_reference Array::operator[]( size_type index ) const
{ rangecheck( index ); // проверка индекса и генерация исключенияreturn elems[index];
}
std::ostream& operator<< ( std::ostream &t, Array const& V )
{ if( V.size() > 0 )
for( std::size_t i = 0; i < V.size(); ++i) t << V.elems[i] << ' ';
return t;
}
В реализациях типы, объявленные в typedef, пишутся без префиксов. А если тип — возвращаемый, то требуется задавать префикс класса. Как внятно сформулировать такое требование? Или это только в Visual C++. NET 2005?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>В реализациях типы, объявленные в typedef, пишутся без префиксов. А если тип — возвращаемый, то требуется задавать префикс класса. Как внятно сформулировать такое требование? Или это только в Visual C++. NET 2005?
Ну ты даешь Срочно в отпуск!!!
Твои typedef-ы в какой области видимости объявлены?
Правильно, в классе.
Значит, где их можно поминать без квалификации?
Правильно, только в той же или вложенной области видимости (т.е. только внутри класса и его членов/наследников).
А функция в какой области видимости объявлена?
Правильно, на уровне пространства имен, т.е. в области, внешней по отношению к твоему классу.
Так чему ж ты удивляешься?
Здравствуйте, jazzer, Вы писали:
LVV>>В реализациях типы, объявленные в typedef, пишутся без префиксов. А если тип — возвращаемый, то требуется задавать префикс класса. Как внятно сформулировать такое требование? Или это только в Visual C++. NET 2005? J>Ну ты даешь Срочно в отпуск!!!
Не... К сожалению, мне еще полтора месяца на реботе телепаться... J>Твои typedef-ы в какой области видимости объявлены? J>Правильно, в классе. J>Значит, где их можно поминать без квалификации? J>Правильно, только в той же или вложенной области видимости (т.е. только внутри класса и его членов/наследников). J>А функция в какой области видимости объявлена? J>Правильно, на уровне пространства имен, т.е. в области, внешней по отношению к твоему классу.
То есть возвращаемый тип из метода класса относится к внешней области видимости. Тут можно провести аналогию с перегрузкой: возвращаемый тип не учитывается при перегрузке. Так легче запомнят. J>Так чему ж ты удивляешься?
Не удивляюсь, а просто принимаю как есть, не особо задумываясь о причинах.
Надо префикс писать — значит пишем, можно не писать — не пишем...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
J>>А функция в какой области видимости объявлена? J>>Правильно, на уровне пространства имен, т.е. в области, внешней по отношению к твоему классу. LVV>То есть возвращаемый тип из метода класса относится к внешней области видимости. Тут можно провести аналогию с перегрузкой: возвращаемый тип не учитывается при перегрузке. Так легче запомнят.
Возвращаемого типа, как ты о нем говоришь, не существует в природе.
Существует сигнатура функции, которую ты объявляешь, и всё (и возвращаемый тип, и типы аргументов) в ней находится в той области видимости, где ты ее объявляешь, в твоем случае — в области, внешней по отношению к классу, которая внутренних имен класса не увидит, пока ты не ткнешь ее туда носом (при помощи квалификации).
Ты с тем же успехом можешь попытаться объявить переменную внутреннего типа класса — тут у тебя не возникает вопросов, почему надо явно квалифицировать:
Array::value_type dummy;
J>>Так чему ж ты удивляешься? LVV>Не удивляюсь, а просто принимаю как есть, не особо задумываясь о причинах. LVV>Надо префикс писать — значит пишем, можно не писать — не пишем...
Стыдись! А потом удивляешься, почему студенты тупо зубрят и ничего не понимают при этом.
Здравствуйте, jazzer, Вы писали:
J>>>А функция в какой области видимости объявлена? J>>>Правильно, на уровне пространства имен, т.е. в области, внешней по отношению к твоему классу. LVV>>То есть возвращаемый тип из метода класса относится к внешней области видимости. Тут можно провести аналогию с перегрузкой: возвращаемый тип не учитывается при перегрузке. Так легче запомнят. J>Возвращаемого типа, как ты о нем говоришь, не существует в природе. J>Существует сигнатура функции, которую ты объявляешь, и всё (и возвращаемый тип, и типы аргументов) в ней находится в той области видимости, где ты ее объявляешь, в твоем случае — в области, внешней по отношению к классу, которая внутренних имен класса не увидит, пока ты не ткнешь ее туда носом (при помощи квалификации).
Фигасе! Все имена, объявленные в typedef, прекрасно распознаются без всяких префиксов. И в списке параметров, и внутри тела метода. Кроме тех, которые объявлены на месте возвращаемого типа. Вот я и спрашиваю — мож особенность Mикрософта? J>Ты с тем же успехом можешь попытаться объявить переменную внутреннего типа класса — тут у тебя не возникает вопросов, почему надо явно квалифицировать: J>
J>Array::value_type dummy;
J>
Это совсем другое дело! Вне тела определяемого метода — так и делается, и тут вопросов не возникает. Внутри тела — прекрасно и без префикса работает. J>>>Так чему ж ты удивляешься? LVV>>Не удивляюсь, а просто принимаю как есть, не особо задумываясь о причинах. LVV>>Надо префикс писать — значит пишем, можно не писать — не пишем... J>Стыдись! А потом удивляешься, почему студенты тупо зубрят и ничего не понимают при этом.
Не, в нашем деле тупо не позубришь. Я требую, чтоб прога работала. Причем, на машине заказчика, то есть в учебном классе. Если ему для этого требуется с префиксом класса познакомиться — так пусть в MSDN слазит и почитает.
А я вот любопытный, меня и интересует, почему то с префиксом, то без префикса.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, jazzer, Вы писали:
J>>>>А функция в какой области видимости объявлена? J>>>>Правильно, на уровне пространства имен, т.е. в области, внешней по отношению к твоему классу. LVV>>>То есть возвращаемый тип из метода класса относится к внешней области видимости. Тут можно провести аналогию с перегрузкой: возвращаемый тип не учитывается при перегрузке. Так легче запомнят. J>>Возвращаемого типа, как ты о нем говоришь, не существует в природе. J>>Существует сигнатура функции, которую ты объявляешь, и всё (и возвращаемый тип, и типы аргументов) в ней находится в той области видимости, где ты ее объявляешь, в твоем случае — в области, внешней по отношению к классу, которая внутренних имен класса не увидит, пока ты не ткнешь ее туда носом (при помощи квалификации). LVV>Фигасе! Все имена, объявленные в typedef, прекрасно распознаются без всяких префиксов. И в списке параметров, и внутри тела метода. Кроме тех, которые объявлены на месте возвращаемого типа. Вот я и спрашиваю — мож особенность Mикрософта?
Спасибо, что возразил — полез в Стандарт, конкретно, в 3.3.6/1, последняя строчка длинного абзаца пятого пункта прямо над примером, после последней запятой (чувствую себя юристом)
В общем, область видимости класса в случае функции-члена класса начинается сразу после имени функции:
A::X A::f(....)
^ вот здесь начинается class scope
так что список параметров действительно находится уже внутри области видимости класса.
В принципе, я не вижу особых причин, кроме удобства, делать именно так.
А почему возвращаемое значение должно быть квалифицировано?
Потому что так положено по грамматике: вначале тип, потом идентификатор, потом все остальное (в случае функции — список аругментов в скобках).
И когда мы парсим тип возвращаемоого значения, мы еще не знаем, что там будет дальше — объявление переменной, или определение члена-функции, или еще что-нть. Поэтому мы сначала парсим то, что вначале, смотрим, что это тип, после чего врубаем грамматику для объявлений.
В принципе, конечно, можно было бы потребовать, чтоб компилятор был умным и просто пропускал то, что вначале, пока не распарсит то, что дальше и не поймет, что это определение функции, и уже после этого попытался искать тип в области видимости класса. Навскидку я не вижу, почему это могло бы не работать.
Здравствуйте, jazzer, Вы писали:
LVV>>Фигасе! Все имена, объявленные в typedef, прекрасно распознаются без всяких префиксов. И в списке параметров, и внутри тела метода. Кроме тех, которые объявлены на месте возвращаемого типа. Вот я и спрашиваю — мож особенность Mикрософта?
J>Спасибо, что возразил — полез в Стандарт, конкретно, в 3.3.6/1, последняя строчка длинного абзаца пятого пункта прямо над примером, после последней запятой (чувствую себя юристом) J>В общем, область видимости класса в случае функции-члена класса начинается сразу после имени функции: J>
J>A::X A::f(....)
J> ^ вот здесь начинается class scope
J>
J>так что список параметров действительно находится уже внутри области видимости класса. J>В принципе, я не вижу особых причин, кроме удобства, делать именно так.
Спасибо за ссылку в стандарт, а то я лазил-лазил, и как -то пропустил. J>А почему возвращаемое значение должно быть квалифицировано? J>Потому что так положено по грамматике: вначале тип, потом идентификатор, потом все остальное (в случае функции — список аругментов в скобках). J>И когда мы парсим тип возвращаемоого значения, мы еще не знаем, что там будет дальше — объявление переменной, или определение члена-функции, или еще что-нть. Поэтому мы сначала парсим то, что вначале, смотрим, что это тип, после чего врубаем грамматику для объявлений. J>В принципе, конечно, можно было бы потребовать, чтоб компилятор был умным и просто пропускал то, что вначале, пока не распарсит то, что дальше и не поймет, что это определение функции, и уже после этого попытался искать тип в области видимости класса. Навскидку я не вижу, почему это могло бы не работать.
Да, с точки зрения реализации синтаксического разбора — все логично. Спасибо!
Хочешь быть счастливым — будь им!
Без булдырабыз!!!