Извикахме различна функция operator[].
Когато дефинирате два обекта, единият е константен, а другият е неконстантен по следния начин:
const TextBlock a("Hello");
TextBlock b("World");
Когато използвате a[0]
и b[0]
, ще бъдат извикани различни видове operator[]
. Първият -- a[0]
, ще извика функцията const:
const char &operator[](int) const;
Тъй като a
е константен обект, всяка операция върху него не може да промени стойността му. Така че, когато използва оператора []
, версията const ще бъде извикана и ще върне тип const char&
, което също означава, че не можем да променим стойностите на нейните членове.
От друга страна, вторият -- b[0]
ще извика функцията non-const:
char &operator[](int);
Обектът може да се променя, както и неговият член. Така че тази функция връща тип char &
, който може да бъде модифициран.
Какво се прави в non-const функция?
Така че нека видим връзката между не-константна функция и константна функция. Във вашата програма неконстантната функция се реализира чрез извикване на константна функция.
Обикновено неконстантен обект не може да извика функцията const директно. Но можем да променим атрибута с static_cast<>
. Така можем да трансформираме обект b
в const TextBlock
, така че да може да извика функцията const.
Правим това в char &operator[](int index)
, което може да намали повторното използване на код.
char & operator[](int position)
{
// const TextBlock tmp = *this;
// return const_cast<char &>(tmp[position]);
return
const_cast<char &>( (static_cast<const TextBlock &>(*this))[position] );
}
Когато се използва static_cast<const TextBlock &>(*this)
, той имплицитно дефинира временен обект, който е преобразуването TextBlock &
към const TextBlock &
на *this
.
След преобразуването имаме временен обект и го нарекохме tmp. Така че можем да използваме tmp[0]
за извикване на функцията const, което точно правим.
След като се върнем от функцията const, получаваме стойност, чийто тип е const char &
. Но ние всъщност искаме да е char &
. Затова използваме const_cast<char &>
премахване на атрибута const от върнатата стойност. След това получаваме неконстантна препратка в char, чиито стойности могат да бъдат променяни от нас.
Всъщност изразът return в non-const функция може да бъде заменен по следния начин:
const TextBlcok &tmp = *this;
return const_cast<char &>tmp[position];
tmp
е временната препратка към *this (Не е временен обект). Имаме имплицитно преобразуване от TextBlock &
в const TextBlock &
тук, докато има изрично преобразуване в оригиналния израз за връщане.
Не забравяйте да добавите &
в първия израз, което означава, че използваме препратка към обект вместо реален обект. Или ще извика конструктор на присвояване, за да генерира нов обект. Ако се случи, tmp
няма да има нищо общо с *this
. Те са различен обект, дори ако имат еднаква стойност. Каквото и да променим tmp, действителният обект, който искаме да управляваме, няма да се промени!
person
WingCuengRay
schedule
20.01.2016