2012-06-20 7 views
13

Как и в случае с Скоттом Мейерсом, чтобы предотвратить повторение кода в версии-константе геттера и неконстантной версии геттера, вызовите версию версии метода из неконстантной версии: static_cast<const A&>(*this).Methodology();однако, в случайном порядке использование из-за чрезмерного зрения Visual Assist X Intellisense Я набрал: const_cast<const A&>(*this).Methodology();, и он работал отлично.Разница между C++ между добавлением константы с static_cast и const_cast этого «объекта»?

Каковы все различия в этом случае с использованием конкретного броска?

IDE в использовании: Visual Studio 2010.

+1

Интересно, почему Scott продвигает использование static_cast, в то время как const_cast кажется более подходящим выбором здесь, а также более четко выражает намерение? Или вы не используете его точно так, как он имел в виду? – stijn

+0

@stijn: Я тоже задавался вопросом о том же. 'const_cast' чувствует себя немного более естественным для меня даже для более безопасного направления добавления' const'. –

+0

@CharlesBailey: см. Мой ответ, чтобы понять, почему он не продвигал друг друга. – Casey

ответ

5

Предполагая, что тип this является A*, нет никакой разницы.

В общем const_cast может бросить Визитки в const спецификатор (с любого уровня косвенности или параметра шаблона)

static_cast<> может бросить тип в другой, если целевой тип в иерархии типов источника.

Они не могут выполнять работу друг друга. не

Причины они оба работали в вашем случае, потому что вы ввел константных-Несс, в отличие от прихватив его (звонит из неконстантной версии функции типа this является A*, не Const). Вы могли бы так же хорошо написать

const A& tmp = *this; 
tmp.Methodology(); 

и это сработало бы без необходимости кастинга. Кастинг используется для удобства и ограниченности, чтобы не вводить новую переменную.

Примечание: вы можете использовать static_cast<> здесь, как вы знаете, что вы литье на правильный тип. В других случаях (когда вы не можете быть уверены), вам необходимо использовать dynamic_cast<>, что делает проверку типа во время выполнения, чтобы обеспечить преобразование действует

+0

'A' - тип класса,' this' по умолчанию 'const * A'. – Casey

+0

@ Кейси - я так много думал; дело в том, что это класс, в котором вы это делаете, а не, например, подкласс (в этом случае 'const_cast <>' потерпел бы неудачу) – Attila

+1

@Casey - тип 'this' является' const A * '(более точно 'const A * const'), если вы находитесь в функции' const' member, иначе это 'A *' (точнее 'A * const') – Attila

3

После повторного чтения Пункта 3 из Effective C++ 3rd Ed. Я понимаю, что он был на самом деле выступает с использованием как , Добавьте const для вызова версии const, затем отбросьте константу возвращаемого значения (если она есть). В моем конкретном случае нет значения константы const, просто const-функция, поэтому версия wrapped by-const_cast <> не нужна и фактически вызывает . Разница между двумя указанными вызовами

(стр. 13) Пункт 3: ИспользованиеConstпо возможности

...

(стр.23) избежать дублирования всопзЬиНепро- константныеФункции-члены

... То, что вы действительно хотите сделать, это реализовать оператор [] функциональность один раз и использовать его дважды. То есть вы хотите иметь одну версию оператор [] позвоните другому. И это приводит нас к отбрасыванию совести.

... Кастинг прочь сопзИте на возвращаемом значении является безопасным, в этом случае, , потому что тот, кто называется не- оператор Const [] должен был иметь не- Const объект в первое место .... Так имеющий не- сопзЬ оператор [] называют Const версия является безопасным способом, чтобы избежать дублирования кода , даже если это требует слепок ...

class TextBlock { 
public: 

... 

    const char& operator[](std::size_t position) const  //same as before 
    { 
     ... 
     ... 
     ... 
     return text[position]; 
    } 

    char& operator[](std::size_t position)  //now just calls const op[] 
    { 
     //cast away const on op[]'s return type; 
     //add const to *this's type; 
     //call const version of op[]. 
     return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]); 
    } 
... 
}; 

Как вы можете видеть, код имеет две отливки, а не одну. Мы хотим, чтобы не- Const оператор [] ... Чтобы избежать бесконечной рекурсии, мы должны указать, что мы хотим вызвать оператор константных [], но нет прямого способа сделать это. Вместо этого, мы бросаем * этот из своего родного типа из TextBlock & к Const TextBlock &. Да, мы используем отливку до добавить const! Таким образом, мы имеем два слепков: один, чтобы добавить сопзЬ к * это (так, что наш призыв к оператору [] будет называть сопзЬ версии), второго удалить сопзЬ от * сопзИте operator [].