2015-04-20 2 views
0

В примере кода вызов message() никогда не повлияет на содержимое класса, поэтому я хотел бы, чтобы этот метод был const. Но я не хочу, чтобы возвращаемое значение также было const, так безопасно использовать const_cast, как показано ниже? или есть лучшее решение?Действительно ли это использование const_cast?

EDIT: Извините .. так n_ - указатель!

EDIT2: Мне, наконец, удалось правильно создать проблему. Что делать, если n_ является массивом, как в int n[100]? Тогда я вижу проблему без const_cast.

class A 
{ 
private: 
    int n_[10]; 

public: 
    /* ... */ 

    int* n() const 
    { 
     return const_cast<int*>(n_); 
    } 
}; 
+4

Да, но не нужно. Вы не возвращаете ссылку, поэтому вызывающий может не модифицировать 'n_', вызывая' n() '. – jxh

+1

Текущий код пытается вернуть 'int *' как 'int'. –

+0

Теперь вы позволите мне сделать это: 'const A a; int * p = a.n(); p [0] = 2; '. Нет, это не безопасно. – chris

ответ

5

Нет, это не является допустимым использование const_cast.

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

Возможно, вам также понадобится версия const, которая возвращает const int*. Это тот же принцип, что, например, std::vector::operator[]. Несмотря на то, что оператор не модифицирует вектор, он предоставляет доступ для изменения вектора, и поэтому он не является функцией const. (Но есть и константный перегруженная версия, которая возвращает константную ссылку, тем самым не дающим право изменять вектор)

7

Возвращение типа (не ссылка) выступит с сообщением копию объекта вы возвращающимся. Таким образом, нет необходимости бросать его, копия может быть изменена без ущерба для оригинала. Код будет скомпилирован, если вы удалите const_cast.

Редактировать: в соответствии с последними изменениями на вопрос, я бы сказал, что это злоупотребление const_cast. Принцип, которым придерживается C++, состоит в том, что функция-член const должна не только не вносить никаких изменений в объект, но и не должна возвращать ничего, что могло бы быть использовано для внесения изменений вне функции. Возвращая указатель не-const к переменной-члену, вы нарушаете этот принцип.

+0

Внутри контекста этой функции не 'n_' неявно' const'? – tadman

+0

Не могли бы вы увидеть мое редактирование? Я сделал большую ошибку в оригинальном посте. – xiver77

+0

@tadman да, но вы можете сделать копию переменной 'const' без каких-либо проблем. –

0

вы можете просто вернуть n_, как это

int n() const 
{ 
    return n_; 
} 
0

Там нет необходимости использовать слепок. В функции this->n_ является указателем const, который не указывает на const int.

int* n() const 
{ 
    // No need for a cast. 
    return n_; 
} 

Это имеет смысл возвращать const int* из функции const. Вы не хотите что-то вроде этого:

const A a; 
a.n()[0] = 10; 

Это извращает const -ness объекта. Вы можете предотвратить это с помощью:

const int* n() const 
{ 
    // No need for a cast either. 
    return n_; 
} 
0

Вообще говоря, бросая T const к T с const_cast<> почти всегда ненужными. Это связано с тем, что постоянный объект преобразуется в непостоянный временной, и это можно безопасно выполнить без приведения.

int const n; // n is a constant int 
int x = n;  // perfectly safe 

Это верно, даже если T тип указателя. не

int * const n; // n is a constant pointer to an int 
int * x = n; // perfectly safe 

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

const int * n; // n is a pointer to a constant int 
int * x = n // error, x is a pointer to an int 

Вы можете видеть, что x указывает на что-то другое, чем то, n указывает на, и поэтому инициализация будет выполнена. В этом случае инициализация потребует const_cast<>:

int * x = const_cast<int *>(n); 
       // cast away the const-ness that n is pointing to 

Вы должны сделать это, только если вы знаете, что n на самом деле modifyable (он не может быть, если указатель к фактической памяти только для чтения), или если вы знаете, что пользователь x на самом деле не попытается изменить содержимое, на которое указывает n.


Для примера, вы, кажется, считает, что ваш метод const должен возвращать указатель на данные, хранящихся на вашем объект таким образом, чтобы данные были изменяемыми вызывающим. То есть, поскольку метод n() объявлен const, это означает, что содержимое доступного объекта должно считаться постоянным. Таким образом, n_ представляет собой массив констант int, который будет распадаться на указатель на константу int, но вы хотите вернуть указатель на int.

Если вы намерены изменить n_, независимо от того, обрабатывается ли объект как постоянный, вы можете объявить это намерение с использованием mutable. Это приведет к тому, что n_ будет рассматриваться как непостоянный, даже если содержащий объект const, и поэтому он делает ненужным const_cast.

class A 
{ 
private: 
    mutable int n_[10]; 

public: 
    /* ... */ 

    int* n() const 
    { 
     return n_; 
    } 
}; 
Смежные вопросы