2013-11-20 2 views
0

Являются ли эти определения pointer() равными?Возвращающий указатель на элемент класса из функции const-члена

class Example 
{ 
public: 
    AnotherClass* const pointer() const; 
    AnotherClass* pointer() const; 


private: 
    AnotherClass* m_pointer; 
} 

Гарантирует ли это, что кто-то не может изменить память m_pointer?

+1

Вы хотите, чтобы переменная-член 'm_pointer' оставалась неизменной или указывала память? –

+0

Память указал. Спасибо, я не задал точного вопроса. – Eugene

ответ

1

Две перегрузки для pointer различаются только по типу возврата. Ваш компилятор C++ не примет этого, это ошибка.

Предполагая, что указатель() просто возвращает m_pointer:

Декларация AnotherClass* pointer() const; подвергнет значение m_pointer. Пользователи класса не смогут изменять m_pointer, но они могут изменить объект, на который указывает m_pointer.

Объявление AnotherClass* const pointer() const; очень похоже на AnotherClass* pointer() const;, но возвращаемое значение (временный указатель) является константой. Это объявление не имеет смысла, поскольку вы уже не можете изменить возвращаемое значение в первом объявлении. Вы не можете написать example.pointer() = nullptr в обоих случаях. И когда вы присваиваете возвращаемое значение переменной, как в p = example.pointer(), не имеет значения, если возвращаемое значение указателя() const или нет.

В объявлениях const AnotherClass* pointer() const; и AnotherClass const * pointer() const; будет отображаться значение m_pointer. Пользователи класса не смогут изменять m_pointer, и они не смогут изменить объект, на который указывает m_pointer.

+0

Является ли он аналоговым: int * const и int const *? – Eugene

+0

@Eugene Извините, я допустил ошибку. Теперь я обновил свой ответ. Надеюсь, теперь это ясно. –

2

Вам нужен тип возврата для первого способа быть один из них:

AnotherClass const * pointer() const; 

или

const AnotherClass* pointer() const; 

То, что вы сделали, это возвращает указатель на константный к не- const объект.

То, что вы хотите это неконстантной указатель на объект сопзИте.

Кроме того, чтобы следовать типичной практике, ваш второй метод не должен быть const.

AnotherClass* pointer(); 
1

Есть несколько вещей, чтобы рассмотреть здесь:

Что такое const: указатель или pointee?

Давайте рассмотрим различия между этими различными декларациями.

int x, y; 

int  *  p = &x; // 0 
const int *  p = &x; // 1 
int const *  p = &x; // 2 
int  * const p = &x; // 3 
const int * const p = &x; // 4 
int const * const p = &x; // 5 

(0) означает, что p может измениться (p = &y; ОК) и то, что он указывает (x) может быть изменен с помощью p (*p = y; ОК).

(1) и (2) эквивалентны и означают, что p может измениться (p = &y; ОК) и то, что он указывает (x) не может быть изменен с помощью p (*p = y; ошибка).

(3) означает, что p не может изменить (p = &y; ошибка) и то, что она указывает на (x) может быть изменен с помощью p (*p = y; ОК)

(4) и (5) эквивалентны и означает, что p не может измениться (p = &y; - это ошибка), и то, на что он указывает (x), не может быть изменено с помощью p (*p = y; - это ошибка).

простой способ запомнить это смотрит на * и думать, что он разделяет объекты на константность, то есть,

(а) const перед тем * (например const int * [...] или int const * [...]) означает заостренный предмет (тип int) - const; и

(б) после того, как const* (например [...] * const p [...];) означает, что указатель const и не может быть изменен.

Что произойдет, если функция возвращает объект const?

Рассмотрим:

class some_class; 

const some_class a(); // equivalent to 'some_class const a();' 
     someclass b(); 

const int  c(); // equivalent to 'int const c();' 
     int  d(); 

Тогда (при условии, some_class имеет оператор доступного присваивания) имеем:

some_class x; 

a() = x; // illegal : the returned object is const 
b() = x; // OK  : the returned object is not const 

Это естественно полагать, что c() и d() ведут себя так же, но это не:

c() = 0; // illegal 
d() = 0; // also illegal!!! 

Причина в том, что если функция возвращает фундаментальный тип (например, int, bool, char, любой тип указателя, ...), то возвращенный объект не может быть назначен. Поэтому , возвращающий const объект фундаментального типа, ведет себя так же, как возвращать неконстантный один.

Как насчет перегрузки по типу возврата?

Рассмотрим

int f(); // first overload. 
double f(); // second overload. 

Это незаконно. Мы не можем перегружать только возвращаемый тип. Одна из причин заключается в том, что мы всегда можем игнорировать объект, возвращаемый функцией. Например, если разрешена перегрузка по типу возврата, то какая перегрузка f будет вызываться ниже?

int main() { 
    f(); // which f? 
    return 0; 
} 

Отвечая на вопрос ...

Рассмотрим первую декларацию

AnotherClass* const pointer() const; 

Из того, что мы видели, это означает, что pointer() возвращает const объект типа AnotherClass* (указатель тип). Так как тип указателя является фундаментальным типом, функция pointer выше ведет себя так же, как если бы он был объявлен как

AnotherClass* pointer() const; 

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

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

это Гарантирует ли мне, что кто-то не может изменить m_pointer памяти указал?

Нет, опять же, как перегруженные ведут себя так же, и возвращает указатель на объект, который может быть изменен с помощью этого указателя. То, что вы хотите, это:

const AnotherClass* pointer() const { return m_pointer; } 
// or 
// AnotherClass const* pointer() const { return m_pointer; } 

Обратите внимание на const слева от *.

+0

Очень подробное объяснение const, удивленное, вы никогда не упоминаете соглашение о порядке чтения справа налево. –

Смежные вопросы