2012-06-11 1 views
1

У меня есть функция, которая возвращает указатель на объект. Как это:Предотвращать изменения объекта, возвращаемого как указатель

class SomeClass 
{ 
public: 
    Object* getObject() const { return &obj; }; 
private: 
    Object obj; 
} 

Проблема заключается в том, что я не вызывающую функцию, чтобы изменить возвращаемый объект, он может вызывать функции, которые работают на него внутри, но не изменить OBJ внутри SomeClass .. . примером может быть проще понять:

-Если функция возвращает указатель на константный объект const Object* getObject() const вызываемая функция не будет иметь возможность использовать не константные методы объекта (но я хочу, чтобы они были состояние).

-Если я просто возвращает указатель, функциями вызова может изменить объект:

Object* pointer = sclass.getObject(); 
*pointer = Object(); 

Так объект внутри sclass теперь другой объект (который я не хочу, чтобы это произошло).

Есть ли обходной путь?

+0

Основная проблема заключается в том, что я не» t хотите потерять объект, который был ранее сконструирован/инициализирован ... –

+2

Уточнение: хотите ли вы использовать неконтентные методы для объекта, но не хотите, чтобы возвращаемый указатель указывал на другой объект? –

+0

@Hans Правильно! –

ответ

8

tl; dr версия: Возврат const Object *.

Если функция возвращает указатель на константный объект const Object* getObject() const функция вызова не будет иметь возможности использовать не константные методы объекта (но я хочу, чтобы они были в состоянии).

Но это целая точка const -корректность! Любой метод Object, который не изменяет наблюдаемое состояние объекта, должен быть объявлен const. Если вы согласны в этом, ваша проблема должна исчезнуть. Если вы не знаете , то все это разваливается (что, вероятно, является причиной вашей проблемы!).

Очевидно, что вы не можете ничего о const методов, которые затем подорвать вещи отбрасывая на const -ness из this сделать, но это всегда проблема.

+0

Если целью является использование методов 'const', то одним из способов может быть копирование объекта на сайте вызова:' Object foo = * (sclass.getObject()); foo.nonConstMethod(); '. Также задается вопросом, почему OP не использует ссылки ... – cdhowie

+0

@cdhowie Но тогда объект внутри SomeClass не будет затронут вызываемыми функциями ... Я не использую ссылки, потому что моя программа сложнее, чем эта простой пример ... –

+0

@TiagoCosta Затем вам нужно решить, является ли этот объект неизменным или нет. Если это не должно измениться, верните указатель на постоянный объект, иначе нет. Вы не можете иметь это в обоих направлениях. – cdhowie

2

Если вы не хотите, чтобы пользователь мог изменять объект, верните указатель на объект const.

Предполагая, что ваш объект является const-правильным, это означает, что они смогут делать что-либо/все, что не изменяет объект. Если это не так, то вы хотите исправить проблему со const-правильностью, чтобы это произошло (например, все функции-члены, которые не изменяют объект, получают отметку const).

1

Как уже указывалось выше, если API-интерфейсы объектов не применяют корректность const, вы не можете запретить им изменять его функции. Пока что идеальный объектно-ориентированный дизайн.

Обходной метод (который я бы не сделал сам) мог бы вернуть копию объекта из метода getObject().

Object* getObject() const { Object* o = new o(obj); return o; }; 

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

+1

Это обходное решение более чисто реализовано как 'Object getObject() const {return obj; } '- это изменение API, но для этого требуется, чтобы пользователь« удалял »возвращаемый указатель. –

+0

@unni, Что делать, если нет конструктора, который принимает obj? Или что, если создание объекта тяжело? Это const-correctness, которая требуется, как это было предложено другими. – Jagannath

0

Я только понял, что вы могли бы получить свой торт и съесть его тоже ... при условии, что у вас есть контроль над реализацией класса Object.

В вашем конкретном примере, если оператор присваивания (operator=()) отключена для Object, то выражение

*pointer = Object(); 

становится недействительным.

Примечание: конечно, влияние этого решения больше, чем просто SomeClass::getObject(): ни одна другая часть кода будет иметь возможность назначать экземпляры Object с друг другом. Вы должны решить, если это ограничение стоит для вас

Примечание: отключить operator=, объявить его как private (и не требуется реализация):

class Object 
{ 
    // ... current member declarations/definitions 
    private: 
    Object& operator=(const Object&); // no implementation 
}; 
Смежные вопросы