Аксессоры С++ - должен ли я возвращать указатель на переменную-член или саму фактическую переменную-член?

У меня есть, надеюсь, простой вопрос. Для моих переменных-членов моих классов, все из которых являются частными, должен ли я использовать методы доступа для возврата указателя или для возврата самой переменной? Или я должен делать что-то еще?

Пример:

unsigned int *Object::GetObjectIDPointer()
{
    return &objectID;
}

OR

unsigned int Object::GetObjectID()
{
    return objectID;
}

person Interminable    schedule 06.07.2012    source источник
comment
Лучший способ — избегать аксессоров.   -  person Tadeusz Kopec    schedule 06.07.2012
comment
Не называйте его GetXxxxPointer, когда он возвращает не указатель.   -  person harper    schedule 06.07.2012
comment
@harper Это была небольшая опечатка при копировании и вставке, когда я задавал вопрос. ›‹   -  person Interminable    schedule 06.07.2012
comment
Фактически ваш первый пример делает приватную переменную общедоступной, что противоречит пункту private.   -  person molbdnilo    schedule 06.07.2012


Ответы (4)


Это во многом зависит от того, что вы хотите с ними делать: если вы планируете, чтобы пользователи вашего класса могли изменять переменные внутри вашего класса (ужасная и крайне обескураживающая вещь), вы можете возвращать указатели или ссылки; в противном случае вернуть саму переменную.

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

person Sergey Kalinichenko    schedule 06.07.2012
comment
Я не согласен. Почти никогда не следует возвращать указатель на член или возвращать значение из функции-получателя. Ссылки возврата и константные ссылки почти всегда. - person Mooing Duck; 06.07.2012
comment
@MooingDuck Я следую этому правилу и возвращаю ссылки, когда пишу свой код шаблона, но в коде, не являющемся шаблоном, я принимаю решения в каждом конкретном случае. Например, я возвращаю int по значению, а не по константной ссылке из чисто эстетических соображений. - person Sergey Kalinichenko; 06.07.2012

Я бы сказал, выберите второе решение.
В более общем случае вы можете вернуть копию самого объекта, компилятор, вероятно, оптимизирует любые ненужные копии с помощью оптимизация исключения копирования.

Вы также можете вернуть константную ссылку на поле:

const MyType& getMyField() const { return this->myField; }

Таким образом, копии не создаются и значение не может быть изменено (кроме const_cast).

Но для int я думаю, вы должны вернуть копию, как во втором решении:

unsigned int Object::GetObjectIDPointer()
{
    return objectID;
}
person Mesop    schedule 06.07.2012
comment
возврат ссылок, однако, может быть опасным. Вызывающие также могут сохранять ссылку (const MyType& m = something.getMyField();), которая может стать зависшей. - person Sebastian Mach; 06.07.2012
comment
@phresnel: с указателями та же проблема, и обходные пути могут быть очень медленными. Возврат по ссылке — лучший вариант. olchauvin: RVO помогает только тогда, когда вы возвращаете локальную переменную. При возврате члена он все равно должен делать полную копию. - person Mooing Duck; 06.07.2012
comment
@MooingDuck Вы правы, я имел в виду копирование elision. Я исправил ответ. - person Mesop; 06.07.2012

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

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

Если вы возвращаете ссылку (или указатель), убедитесь, что у вас есть перегрузка const, иначе вы не сможете прочитать значение из const объектов:

const unsigned int *Object::GetObjectIDPointer() const
{
    return &objectID;
}
person Mike Seymour    schedule 06.07.2012
comment
Я не согласен. Почти никогда не следует возвращать указатель на член или возвращать значение из функции-получателя. Ссылки возврата и константные ссылки почти всегда. - person Mooing Duck; 06.07.2012
comment
@MooingDuck: зависит от типа, как я уже сказал. Возврат небольших типов POD (например, в вопросе) по значению обычно быстрее и безопаснее, чем по ссылке; и я предположил, что ссылки предпочтительнее указателей, но не хочу диктовать стиль, если OP предпочитает указатели. - person Mike Seymour; 06.07.2012

Это зависит от вашего метода

GetObjectIDPointer() 

если это частный метод, используйте указатель, так как это ускорит доступность вашего члена. но если метод общедоступен, вы всегда должны возвращать копию. Как будто вы вернете указатель, он нарушит основные принципы OOPS (скрытие данных).

person Apoorva sahay    schedule 06.07.2012
comment
возвращать член по указателю в приватной функции просто глупо. - person Mooing Duck; 06.07.2012