Почему я могу предоставлять приватные члены, когда возвращаю ссылку из публичной функции-члена? - PullRequest
9 голосов
/ 16 января 2011

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

#include <iostream>
#include <cstdlib>

class foo
{
    int x;
    public:
        foo(int a):x(a){}
        int methodOne() { return x; }
        int& methodTwo() { return x; }
};

int main()
{
    foo obj(10);
    int& x = obj.methodTwo();
    x = 20;              // With this statement, modifying the state of obj::x

    std::cout << obj.methodOne();
    getchar();
    return 0;
}

А что касается этого метода, что означает тип возврата? А также, когда я должен иметь тип возврата такого рода?

int& methodTwo() { return x; }

PS: Извините, если тема нечеткая. Может кто-то изменить его на содержание, соответствующее здесь. Благодарю.

Ответы [ 5 ]

19 голосов
/ 16 января 2011

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

Это плохая практика для получения возвращенной закрытой переменной по ссылке?

Нетэто зависит от того, что вы хотите.Такие вещи, как std::vector<t>::operator[], было бы довольно сложно реализовать, если бы они не могли возвращать не-const ссылку :) Если вы хотите вернуть ссылку и не хотите, чтобы клиенты могли ее изменить, просто сделайте ееconst ссылка.

3 голосов
/ 16 января 2011

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

2 голосов
/ 16 января 2011

Этот код:

 int& methodTwo() { return x; }

Означает, что функция возвращает ссылку на целое число. Так же, как при передаче значения по ссылке на функцию, если изменяется возвращаемое значение methodTwo, так и значение, возвращаемое methodTwo. В этом случае поле класса x.

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

Помните общедоступный / частный / защищенный только во время компиляции . Как только ваше приложение скомпилировано, закрытые поля располагаются рядом с открытыми полями, и защита от модификации не защищена. То же самое верно для управляемых языков, таких как C # и Java.

Как правило, вам не следует возвращать ссылки, потому что это затрудняет понимание, когда конструктор / деструктор вызывается. Тем не менее, возврат ссылки может быть быстрее. Если ваш метод возвратил структурный тип, который был ОГРОМНЫМ, возвращение константной ссылки на тот же тип структуры должно занимать всего четыре-восемь байтов (указатель на этот объект). Тем не менее, есть лучшие способы оптимизации для такого рода вещей.

0 голосов
/ 16 января 2011

Я могу получить доступ к закрытой переменной-члену вне области действия класса

Если вы ссылаетесь на x в main(), то это отличается от x, объявленного в class foo. Если вы попытаетесь получить доступ к obj.x, компилятор определенно пожалуется.

Плохо ли получать возвращенную приватную переменную по ссылке?

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

относительно этого метода, что означает возвращаемый тип? А также, когда я должен иметь тип возврата такого рода?

Не уверен, какой метод вы используете?!?!?!

0 голосов
/ 16 января 2011

Как сказал Донотало, это совершенно правильно. Идея наличия закрытых членов состоит в том, чтобы запретить другим классам / функциям доступ к закрытому члену класса без вашего разрешения. Если вы счастливы создать функцию, позволяющую другим классам / функциям получать доступ к вашим закрытым членам, компилятор на самом деле ничего не имеет против этого: -)

Обычно полезно иметь закрытый член и функцию get , чтобы другие классы / функции могли получить значение функции, но только класс сможет ее изменить.

...