Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
vasea_morozov
0 / 0 / 0
Регистрация: 18.06.2014
Сообщений: 16
#1

Возврат ссылки на закрытый элемент данных с++ - C++

21.08.2015, 01:45. Просмотров 538. Ответов 19
Метки нет (Все метки)

Я не могу понять как устроена проблема с возвратом ссылки на закрытый элемент данных.
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Time{
public:
    int &badSetHour(int hh){
        hour = (hh >= 0 && hh < 24) ? hh : 0;
        return hour;
    };
private:
    int hour;
};
 
 
void main(){
    Time t;
    int &hourRef = t.badSetHour(20);
    hourRef = 30;
    t.badSetHour(12) = 74;
        system("pause");
 
}
Во первых что и как делает строка 3(точнее как влияет &)?
Во вторых сама тема... Как устроена проблема с возвратом ссылки на закрытый элемент данных.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.08.2015, 01:45
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Возврат ссылки на закрытый элемент данных с++ (C++):

Возвращение ссылки или указателя на закрытый элемент класса. - C++
Всех уважаемых форуман. поздравляю с наступившим новым годом и прошу ответить на такой вопрос. Почему до сих пор современный C++ не...

Возврат ссылки - C++
Задача которая считывает массив и определяет минимальный, макисмальный, первый отрицательный элемент, и их индексы. По заданию надо ее...

Возврат ссылки - C++
int &amp; function(int); Понятно для чего передают аргументы в функцию как указатели или ссылки.Но зачем функция возвращает ссылку? Чтобы...

Возврат ссылки из функции - C++
Изучаю С++, знаю С. Вот такой простенький вопросик есть. В чем вообще разница: class Str { public: Str func() {return...

Возврат ссылки на функцию. - C++
Здравствуйте, можете пожалуйста объяснить чем отличается когда функция создается просто каким то типом, и когда она создается ссылкой на...

Возврат константной ссылки из функции - C++
Можно ли из функции возвращать константную ссылку? Есть след. классы: class A { /*чтото тяжёлое, сотни байт, например массив, или...

19
Renji
2113 / 1472 / 346
Регистрация: 05.06.2014
Сообщений: 4,264
21.08.2015, 01:59 #2
Цитата Сообщение от vasea_morozov Посмотреть сообщение
Во первых что и как делает строка 3(точнее как влияет &)?
int&link это такой int*link, только всегда разыменован (*link). В стандарте это вроде как немного другими словами, но техническая реализация ссылки 99% что будет именно через указатель.
Цитата Сообщение от vasea_morozov Посмотреть сообщение
Во вторых сама тема... Как устроена проблема с возвратом ссылки на закрытый элемент данных.
Да как-то плевать закрытый он или открытый.
0
vasea_morozov
0 / 0 / 0
Регистрация: 18.06.2014
Сообщений: 16
21.08.2015, 02:19  [ТС] #3
Тут,получается проблема в том что Privat переменную hour можно изменить в обход проверки в 4 строке.
И я пытаюсь понять этот механизм
0
Renji
2113 / 1472 / 346
Регистрация: 05.06.2014
Сообщений: 4,264
21.08.2015, 02:30 #4
Цитата Сообщение от vasea_morozov Посмотреть сообщение
Тут,получается проблема в том что Privat переменную hour можно изменить в обход проверки в 4 строке.
И я пытаюсь понять этот механизм
А никакого механизма нет. Просто модификатор private это не более чем надпись на заборе и никакими защитными свойствами этот забор (переменную) не наделяет. Если компилятор замечает табличку "не влезай, убьет!" он на этот забор лезть отказывается. Если табличку спрятать (вернув ссылку), то полезет и ничего особенного не произойдет. Забор как забор.
2
ASCII
91 / 64 / 10
Регистрация: 15.12.2013
Сообщений: 410
Завершенные тесты: 2
21.08.2015, 02:38 #5
суть в том, что чисто технически данные, объявленные в области private являются закрытыми, что означает, что Вы не сможете напрямую получить к ним доступ, вот пример небольшой:

Напишите в main вот так:
C++
1
2
    Time t;
    t.hour = 10;
И у Вам компилятор выдаст ошибку, мол дружище, ты пытаешься получить доступ к закрытой переменной, а нельзя так. Вот и все, весь механизм private, запретить доступ к данным извне, но никто не мешает Вам вернуть ссылку или же указатель на эти данные через открытую(public) функцию и делать уже с ними что хочешь.

Другое дело, что это считается дурным тоном.
1
vasea_morozov
0 / 0 / 0
Регистрация: 18.06.2014
Сообщений: 16
21.08.2015, 02:52  [ТС] #6
Возможно отхожу от темы...
в какой момент переменная hour принимает новое значение?
C++ (Qt)
1
2
3
int &badSetHour(int hh){
        hour = (hh >= 0 && hh < 24) ? hh : 0; // если тут то как игнорируется условия?
        return hour;
C++ (Qt)
1
2
3
4
 Time t;
    int &hourRef = t.badSetHour(20);// А тут на сколько важно &hourRef какое число будет t.badSetHour(тут)
    hourRef = 30;
    t.badSetHour(12) = 74;
да и потом, я же создал сылку на функцию а не на переменную, ведь так?
0
ASCII
91 / 64 / 10
Регистрация: 15.12.2013
Сообщений: 410
Завершенные тесты: 2
21.08.2015, 03:05 #7
Цитата Сообщение от vasea_morozov Посмотреть сообщение
да и потом, я же создал сылку на функцию а не на переменную, ведь так?
Вот тут вы заблуждаетесь, вы создали функцию, которая возвращает ссылку на тип int.

Ссылка на функцию имеет немного иной вид:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void foo()
{
    std::cout << "Hello from foo()\n";
}
 
int main(int argc, char **argv)
{
    setlocale(LC_CTYPE, ".1251");
    
    void(&lnkToFunc)() = foo;
    lnkToFunc();  // Hello from foo()
    
    std::cin.get();
    return 0;
}
Добавлено через 42 секунды
Та часть объявления функции, которая находится позади имени функции, является возвращаемым типом функции.

Добавлено через 5 минут
Что касается вашего первого вопроса, рассмотрим тогда Ваш код:

C++
1
2
3
4
5
6
7
8
void main(){
    Time t;
    int &hourRef = t.badSetHour(20);
    hourRef = 30;
    t.badSetHour(12) = 74;
        system("pause");
 
}
Создается объект типа Time, затем создается ссылка на тип int, которая инициализируется возвращенным значением метода badSetHour.

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

Так вот, поскольку у нас есть такой псевдоним(напомню его идентификатор hourRef), то когда мы пытаемся присвоить значение для hourRef, оно на самом деле присваивается объекту, на который указывает эта ссылка, то есть на закрытый член данных класса Time.

Отсюда вывод и одновременно ответ на Ваш вопрос:

hourRef = 30;

После этой строки hour будет принимать новое значение.
1
vasea_morozov
0 / 0 / 0
Регистрация: 18.06.2014
Сообщений: 16
21.08.2015, 03:10  [ТС] #8
с этим разобрался.
Если я правильно понял то я создал ссылку на то, что должна вернуть функция, в данном случае переменная hours?
0
ASCII
91 / 64 / 10
Регистрация: 15.12.2013
Сообщений: 410
Завершенные тесты: 2
21.08.2015, 03:11 #9
В следующей строке у Вас также идет изменение этого члена данных, т.к. как я уже сказал, метод возвращает ссылку(псевдоним объекта), а значит есть смысл применить оператор = к вызову такого метода, после чего изменится значение ссылки.

Добавлено через 33 секунды
Цитата Сообщение от vasea_morozov Посмотреть сообщение
с этим разобрался.
Если я правильно понял то я создал ссылку на то, что должна вернуть функция, в данном случае переменная hours?
Да.
1
vasea_morozov
0 / 0 / 0
Регистрация: 18.06.2014
Сообщений: 16
21.08.2015, 03:19  [ТС] #10
Ну что бы закрепить материал, это return возвращает ссылку на hour или этому способствовал &перед именем функции. И вообще на что он( & перед именем функции) повлиял?
0
ASCII
91 / 64 / 10
Регистрация: 15.12.2013
Сообщений: 410
Завершенные тесты: 2
21.08.2015, 03:45 #11
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от vasea_morozov Посмотреть сообщение
Ну что бы закрепить материал, это return возвращает ссылку на hour или этому способствовал &перед именем функции. И вообще на что он( & перед именем функции) повлиял?
return и прочее, это все лишь текст, который транслирует компилятор.
Когда Вы определяете функцию, то попросту говоря, Вы даете инструкции компилятору, каким образом
он должен генерировать объектный код.

Так вот. Когда вы определяете функцию, предположим таким образом:

C++
1
2
3
4
5
int &getNumber()
{
    // ... Какой-то код
    return var;
}
Мы тем самым говорим, что функция getNumber возвращает ссылку на тип int и тут уже компилятор
берет это в учет и когда дело в процессе компиляции дойдет до команды return, он уже не просто
создает ячейку памяти, в которую кладет переменную указанную в команде return, с последующей копией в переменную, которой присваивается(или инициализируется), а он в Вашем случае, где переменная является ссылкой, заставляет ссылаться эту ссылку, на возвращенное значение. Таким образом работа уже происходит не с копией, а с самим элементом.

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

Попросту так: указанный тип возвращаемой функции, влияет на то, что должна возвращать функция через return.

Добавлено через 4 минуты
Ну вообще функции могут возвращать ссылки, указатели, и просто значение.
Последние два случая идентичны.
Если уж Вам так интересно, то представьте себе в самом упрощенном виде оперативную память, выделенную для работы программы как непрерывный блок данных. Представьте ячейки размером в 1 байт, много ячеек...
Не вдаваясь в подробности работы стека:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int var; // глобальная переменная, равна 0
 
// возвращает ссылку на var
int &foo()
{
    return var;
}
 
// возвращает указатель на var
int *foo()
{
    return &var;
}
 
// возвращает значение var
int foo()
{
    return var;
}
Добавлено через 2 минуты
в первом случае, если, при таком коде

C++
1
2
3
// подразумевается, что две другие функции не определены и не объявлены, чтобы
// не было неоднозначного выбора
int &lnk = foo();
Думайте так: lnk станет псевдонимом значения возвращенным функцией foo

Добавлено через 1 минуту
Во втором случае:

C++
1
2
3
// подразумевается, что две другие функции не определены и не объявлены, чтобы
// не было неоднозначного выбора
int *ptr = foo();
Произойдет следующее:
возвращаемое значение foo(), то есть адрес, будет скопирован во временную ячейку в стеке, откуда будет скопирован в ячейку памяти, выделенную под хранение адреса типа int, то есть в нашу переменную ptr.
После чего имеем возможно разыменовать этот указатель и изменить значение.

Добавлено через 3 минуты
в третьем случае:

C++
1
2
3
// подразумевается, что две другие функции не определены и не объявлены, чтобы
// не было неоднозначного выбора
int var = foo();
произойдет тоже самое, что и с указателем, данные таким же образом скопируются, но отличие в том, что возвращаемые данные функции, это значение переменной, а не ее адрес. То есть переменная var получит копию ее значения.

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

Добавлено через 3 минуты
Конечно, ссылка скорей всего в компиляторе реализована как указатель, но это нас не касается.
Главное думать о ссылках, что это не объекты, а псевдонимы объектов.
Так как любое выражение с участием ссылки, будет на самом деле выражением с участием реального объекта, на который она ссылается. Именно по этой причине нет возможности изменить объект на который ссылается ссылка. Поэтому ссылки всегда надо инициализировать.

Добавлено через 33 секунды
Вообще мне кажется, о таком сейчас Вам не стоит задумываться. Просто изучите поведение ссылок и пишите код, практикуйтесь, потом само придет.
1
vasea_morozov
0 / 0 / 0
Регистрация: 18.06.2014
Сообщений: 16
21.08.2015, 14:09  [ТС] #12
Большое спасибо! теперь я понял всё,о чём спрашивал!)
0
Avazart
Эксперт С++
7574 / 5559 / 327
Регистрация: 10.12.2010
Сообщений: 24,934
Записей в блоге: 17
21.08.2015, 18:32 #13
C++
1
2
3
4
int &badSetHour(int hh){
        hour = (hh >= 0 && hh < 24) ? hh : 0;
        return hour;
    };
Стоило вероято начать с того что эта функция делает не понятно что, т.е намерения программиста не очевидны.
Зная что хотел сделать программист можно было бы написать более корректный и очевидный пример.
0
Tulosba
:)
Эксперт С++
4705 / 3240 / 297
Регистрация: 19.02.2013
Сообщений: 9,046
22.08.2015, 14:34 #14
Цитата Сообщение от ASCII Посмотреть сообщение
возвращаемый тип данных в некоторых ситуациях влияет на то, что вернет функция
В некоторых? Я бы сказал, что во всех!
Цитата Сообщение от ASCII Посмотреть сообщение
нет возможности изменить объект на который ссылается ссылка
Неудачная формулировка. Изменить объект можно, но нельзя изменить связь м/у ссылочной переменной и объектом, на который ссылка указывает.

Проводя аналогию с указателями, можно было бы сказать, что ссылка (T&) работает как константный указатель на объект:
C++
1
T* const x = &t; // можно менять данные через 'x', но нельзя сделать чтобы 'x' указывал на объект, отличный от 't'
а ссылка на константу (const T&) - как константный указатель на константный объект:
C++
1
const T* const x = &t; // нельзя менять данные через 'x', и нельзя сделать чтобы 'x' указывал на объект, отличный от 't'
Цитата Сообщение от Avazart Посмотреть сообщение
Стоило вероято начать с того что эта функция делает не понятно что
Это да, но ТС пока ещё учится и лепит всё в кучу, так что простительно.
Обычно сеттеры либо возвращают void (в большинстве случаев), либо предыдущее установленное значение.
0
Avazart
Эксперт С++
7574 / 5559 / 327
Регистрация: 10.12.2010
Сообщений: 24,934
Записей в блоге: 17
22.08.2015, 14:37 #15
Цитата Сообщение от Tulosba Посмотреть сообщение
Это да, но ТС пока ещё учится и лепит всё в кучу, так что простительно.
Спорный вопрос, возможно стоит стремиться сразу же учиться правильно выражать свои мысли в коде.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.08.2015, 14:37
Привет! Вот еще темы с ответами:

Возврат ссылки на локальную переменную - C++
Привет, есть такой код: int*&amp; change(void) { int* x(new int(50)); return x; } int main(void) {

Создание ссылки и возврат из функции - C++
Есть вот такая функция, возвращает максимальный элемент. template &lt;typename Type&gt; inline const Type max_(const Type&amp; a, const Type&amp; b) ...

operator= возврат значения и просто ссылки - C++
Здорова господа! Снова пытаюсь чуток в С++ разобраться, с перегрузкой операций, снова ничерта непонятно. от допустим класс class...

Использование псевдопеременных: bd (3,5) = s, где bd - база данных, s - элемент базы данных, тогда с 3 по 5 элементы базы данных заменить на элемент s. - C++
всем доброго времени суток! есть у меня класс bd, массив элементов этого класса table, а вот сам метод: int copyTable(int a, int b) {...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru