То что я только что узнал не описано ни в одной книге - даже для профи. простейший код: void main(void) { std::list<int> l; std::list<int>::iterator i = l.begin(); std::list<int>::const_iterator ci = l.begin(); // !!! } не поверите но const_iterator begin() const { ... } никогда не вызывается!!! более того он не вызывается даже если этот код написать в констактном методе. более того для VS2003 этот код будет компилироваться только потому что в их библиотеке стл есть наследование простого итератора от константного - т.е. если сделать аналогию своих итераторов но убрать наследование, то нифига не откомпилируется. Вопрос: кто нить из мэтров С++ это описывал подробно!?
А что здесь подробно описывать? Код двух функций одинаков, зачем их две штуки делать? Код (Text): iterator begin() { // return iterator for beginning of mutable sequence return (iterator(_Nextnode(_Myhead), this)); } const_iterator begin() const { // return iterator for beginning of nonmutable sequence return (const_iterator(_Nextnode(_Myhead), this)); } По аналогии: Код (Text): int gint; const int * pint1 (void) {return &gint;} int * pint2 (void) {return &gint;} int _tmain(int argc, _TCHAR* argv[]) { pint1 (); pint2 (); } два раза будет вызвана pint2, даже если ее тип поставить void *
KeSqueer В целях оптимизации. Могут быть различия как в реализации итераторов, так и возвращении последних. Другое дело, что в С++ нет перегрузки функций по типу возвращаемого значения и лично мне не было ясно, как должны различаться вышеприведённые варианты методов.
Они различаются по наличию ключевого слова const после декларации. И выбор между методами делается по простому принципу: если объект, к которому применяется метод, описан как const, то вызывается второй метод, в противном случае - первый. Соответственно в примере systemio оба раза вызывается первый метод, поскольку объект не const. При втором вызове результат автоматически преобразуется к const_iterator - преобразование в эту сторону разрешено, но не наоборот (в <list> описание всего этого после опускания деталей имеет общий вид "class iterator : public const_iterator"). Upd: чтобы вызвать таки const-метод, нужно сделать следующее: Код (Text): void func(const std::list<int> l) { std::list<int>::const_iterator it = l.begin(); // <- здесь вызывается const-метод - если заменить слева const_iterator на // iterator, получим ошибку компиляции } int main() { std::list<int> l; std::list<int>::iterator it = l.begin(); // <- здесь вызывается не const-метод func(l); }
при перегрузке, для мемберных функций учитывается "неявный аргумент" имеющий тип объекта по простому: begin можно заменить на: iterator begin(std::list<int>&); const_iterator begin(const std::list<int>&); // const версия а вызов на: std::list<int> l; std::list<int>::iterator it = begin(l); P.S. естественно это псевдокод, но по сути - так и происходит
еще не совсем понятно для реализации из борланда. там наследования нет - какже идет тогда приведение типа? template<class _Tp, class _Traits> struct _List_iterator : public _List_iterator_base { ... }; template <class _Tp, class _Alloc> class list : public _List_base<_Tp, _Alloc> { typedef _List_iterator<_Tp, _Nonconst_traits<_Tp> > iterator; typedef _List_iterator<_Tp, _Const_traits<_Tp> > const_iterator; };