Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Проблемы, порождаемые наличием константных методов

Желательно встроить средства расширения в язык. | Всегда есть потеря на jmp; | Component Pascal | Предкомпилированные заголовки | Понятие пространства имен | Стандартные конструкторы | Порядок конструирования и разрушения объектов | Множественное наследование | Проблема повторяющихся базовых классов | Замена множественного наследования наследованием от интерфейсов в других языках объектно-ориентированного программирования |


Читайте также:
  1. D) сохранения точных записей, определения установленных методов (способов) и сохранения безопасности на складе
  2. V. ОЦЕНКА КАЧЕСТВА И КЛАССИФИКАЦИЯ ДОКАЗАТЕЛЬНОЙ СИЛЫ МЕТОДОВ, ПРИВЕДЕННЫХ В РАЗДЕЛЕ ЛЕЧЕНИЕ.
  3. Важная часть методического раздела программы — обоснование методов сбора эмпирических данных.
  4. ВАЖНОСТЬ РАЗЛИЧЕНИЯ ЗАДАЧ И МЕТОДОВ
  5. Взаимосвязь методов при изучении литературы.
  6. Выбор методов проведения маркетинговых исследований
  7. Выбор методов производства работ

При объявлении переменных и параметров функций в описании типа может быть указано ключевое слово const.

 

Объявление f(const char *s) означает, что символы, адресуемые указателем s, изменять нельзя.

 

Объявление f(char const *s) означает, что указатель s изменять нельзя.

 

Также можно сделать объявление: f(const char const *s), которое будет означать, что ни указатель, ни переменную изменять нельзя.

 

Если в программе объект объявлен с помощью модификатора const, то у него можно вызывать лишь те методы, которые объявлены с этим же модификатором:

 

Class TTextReader

{

public:

int ItemCount() const;

...

};

 

Наличие константных объектов порождает проблему – огромная избыточность программного кода. Заранее программист не знает, будет ли пользователь (другой программист) его класса создавать константные объекты. Вследствие того, что это не исключено, программист начинает записывать слово const в объявление всех методов, в которых его можно записать. Многие методы являются виртуальными или вызывают виртуальные методы. Случается так, что в производных классах виртуальные методы, вызванные константными методами, модифицируют поля объектов (это требуется по условию задачи). Это приводит к логической проблеме, которая решается либо за счет применения оператора const_cast к указателю this в производных классах, либо за счет объявления полей в производных классах с модификатором mutable (записывается при описании полей класса в том случае, если они должны модифицироваться константными методами).

 

mutable int m_RefCount;

Также решить проблему можно при помощи перегрузки метода класса без модификатора const:

 

classTTextReader

{

public:

int ItemCount() const;

int ItemCount();

int ItemCount() const volatile;

int ItemCount() volatile;

...

};

 


 

Варианты объявления:

 

volatile TTextReader r;

const volatile TTextReader r;

const TTextReader r;

TTextReader r;

 

Ключевое слово volatile запрещает кэшировать значение переменной. Если в программе происходит считывание значения переменной, объявленной с этим ключевым словом, то значение считывается из памяти, а не из регистров, а запись всегда производится в память, в которой размещается данная переменная. Если ключевое слово volatile не указано, то оптимизатор C++ имеет право выполнять

регистровые операции (оптимизации) при чтении и записи переменных, а также размещать их в регистрах.

Операторы приведения типа в языке C++: const_cast, reinterpret_cast, static_cast, dynamic_cast

Static_cast – безопасное преобразование, не содержит за собой инструкций процессора.

 

Существует четыре оператора преобразования типа в С++:

 

reinterpret_cast<тип>(переменная)

static_cast<тип>(переменная)

const_cast<тип>(переменная)

dynamic_cast<тип>(переменная)

 

reinterpret_cast позволяет отключить контроль типов данных на уровне компилятора, с помощью него любой указатель может быть интерпретирован, как любой другой указатель, а также любая память или переменная может быть интерпретирована иначе. В программах этот оператор преобразования типа использовать не следует, так как он нарушает переносимость программ. Его наличие свидетельствует о том, что программа не является кросс-платформенной. Обычно такое приведение типа применяется для низкоуровневого, зависящего от реализации программирования.

 

int i;

char* p;

p = reinterpret_cast<char *>(&i);

 

static_cast используется вместо преобразования тип(переменная), (тип)переменная и (тип)(переменная) при работе с классами, структурами и указателями на них. Он задуман по причине того, что в С++ выражение тип(переменная) может оказаться вызовом конструктора. Если в программе требуется преобразовать тип, а не вызвать конструктор типа, используется данный оператор. Кроме того, оператор (тип)переменная или (тип)(переменная) может в некоторых случаях оказаться преобразованием reinterpret_cast<тип>(переменная), а при разработке кросс-платформенных программ оператор reinterpret_cast всегда содержит потенциальную опасность неправильной работы программы на другой платформе. Поэтому вместо операторов тип(переменная), (тип)переменная и (тип)(переменная) следует использовать операторы reinterpret_cast и static_cast, которые убирают не явность из преобразования. Так как оператор static_cast является громоздким, то для простых типов данных допустимо использование форм: (тип)переменная и(тип)(переменная). Форма тип(переменная) не должна использоваться для преобразования типа. Static_cast допустима только в том случае, если _тип_ может быть неявно преобразовано в тип, который имеет выражение, или наоборот. В любом другом случае приведение типа вызывает ошибку.


 

Сonst_cast используется для приведения не константных указателей к константным и наоборот:

 

void f2(char* s);

void f1(const char* s)

{

...

f1(const char*s);

...

f2(const_cast<char>(s))

...

};

 

Операция const_cast предназначена исключительно для приведения типа, если значение имеет тип const или volatile.

 

const cast < имя_типа > (выражение)

 

Результатом такого приведения типа будет ошибка, если любые другие аспекты типов не совпадают. То есть имя_типа и выражение должны быть одного типа, за исключением того, что они могут отличаться только наличием или отсутствием const или volatile.

 

Операция const_cast не во всем хороша. Она может изменить указатель на величину, но эффект от изменения значения, заданного как const, не определен.

 

void change (const int * pt, int n);

 

int main ()

{

int pop l 38383;

const int рор2 = 2000;

change (& pop1, - 1);

change (& pop2, - 1);

 

void change (const int * pt, int n)

{

int * ре;

if (n < 0)

{

ре = const_ cast<int *> (pt);

*ре = 100;

}

}

 

Так как рор2 объявлен как const, компилятор может защитить его от изменения, как показано в следующем выводе программы:

 

рор1, рор2: 38383, 2000

рор1, рор2: 100, 2000

 

В данном случае компилятор создает временную копию рор2 и присваивает ее адрес ре, но, как уже

говорилось, в стандарте С++ данная ситуация называется неопределенной.

dynamic_cast соответствует оператору as в Delphi. Для работы этого оператора нужно в опциях компилятора включить опцию RTTI. Если это выполнено, то оператор dynamic_cast работает, как static_cast. Оператор dynamic_cast работает по-разному в зависимости от того, применяется он к ссылке на объект (&) или указателю на объект (*). Если оператор применяется к ссылке на объект, то преобразование не может быть выполнено и возникает исключительная ситуация. Если он применяется к указателю на объект и преобразование не может быть выполнено, оператор возвращает NULL.

17. Ссылки в языке C++. Рекомендации по работе со ссылками. Типичные ошибки при работе со ссылками.

 

Ссылки в языке C++

 

Ссылка является альтернативным именем объекта и объявляется следующим образом:

 

int i;

int &r = i;

 

Использование ссылки r эквивалентно использованию переменной i. Основное применение ссылок – передача параметров в функцию и возврат значения. В случае, когда ссылка используется в качестве параметра функции, она объявляется неинициализированной:

 

void f(int &i);

 

Во всех остальных случаях ссылка должна инициализироваться при объявлении, как показано ранее. Если ссылка является полем класса, она должна инициализироваться в конструкторе класса в списке инициализации до тела конструктора. При использовании в качестве параметров функций ссылки соответствуют var-параметрам в языке Delphi:

procedure P(var i: Integer);

 

Константные ссылки соответствуют const-параметрам в языке Delphi:

 

procedure P(const i: Integer);

 

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

 

Cсылка во многом подобна указателю в замаскированной записи, где операция разыменования * предполагается неявно. И, фактически, это в какой-то степени именно то, чем является ссылка. Однако между ссылками и указателями существуют различия помимо обозначений. Одно из таких различий состоит в том, что ссылку необходимо инициализировать в момент ее объявления. Нельзя сначала объявить ссылку, а затем присвоить ей значение.

 

Ссылка во многом аналогична указателю со спецификатором const. Ее следует инициализировать в момент создания, после чего ссылка остается привязанной к определенной переменной до конца программы. Таким образом, конструкция

int & rodents = rats;

 

по сути, является замаскированной записью выражения, подобного следующему:

 

int const * pr = &rats;

 

В данном случае ссылка rodents играет ту же роль, что и выражение *pr.

{

int rats = 101;

int & rodents = rats; // rodents - это ссылка

 

int bunnies = 50;

rodents = bunnies;

}

Программа генерирует следующий вывод:

rats = 101, rodents = 101

адрес rats = Ox0065f d44, адрес rodents = Ox0065fd44

bunnies = 50, rats = 50, rodents = 50

адрес bunnies = Ox 0065fd48, адрес rodents = O0065f d4

 


Дата добавления: 2015-11-16; просмотров: 85 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Понятие константного метода| Рекомендации по работе со ссылками

mybiblioteka.su - 2015-2024 год. (0.013 сек.)