Как передать объект класса по ссылке?
Если Вы «пытаетесь познать C++», то хотя бы книгу откройте по языку. Любую. Тогда таких вопросов появляться не будет.
21 июн 2016 в 18:02
Зря @ixSci читаете нравоучения. Q&A не для дискуссий и высоких материй. Вообще, сходу не нашел ответа на вопрос для Си++ в базе вопросов, так что сам по себе вопрос считаю адекватным, вот первый ответ, близкий по духу. Формулировка, вопроса конечно страдает, требуется правка. Лучше переформулируйте вопрос за автора, он просто не знает, что в нем написать. Думаю, против ни кто не будет.
21 июн 2016 в 18:41
Не понимаю, с чего вдруг Вы тут разводите цензуру. Не нравится вопрос — поднимайте тревогу, пусть модераторы решают. Совсем не обязательно дергать самолюбие авторов. Я вообще такие вопросы пропускаю мимо ушей. Этот привлек внимание как раз отрицательной оценкой.
22 июн 2016 в 8:04
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Передача объекта по ссылке используется достаточно часто и описана во многих книгах по С++, однако не всем получается быстро понять данный механизм.
Для начала рассмотрим принимающую сторону, т.е. функцию или метод класса, в который передается ссылка на объект. В простейшем случае это выглядит так:
void foo(ObjectType& object)
К типу передаваемого объекта добавляется символ & , причем его можно размещать как вплотную к типу, так и к имени объекта. Это зависит от стиля программирования.
При передачи объекта по ссылке не происходит копирования, т.е. мы по сути передаем адрес на объект, что быстрее и менее затратно по памяти. Плюс ко всему мы работаем непосредственно с объектом, переданным по ссылке. Если же объект исключительно входной и не должен быть изменен, то следует добавить модификатор const:
void foo(const ObjectType& object)
Теперь, изменить объект object в функции не получится. Чтобы было возможно вызывать методы класса object они должны быть объявлены как const . Следует отметить, что есть понятие «ссылки на константу» а есть «константная ссылка». В данном случае мы имеем дело с первым понятием.
Теперь перейдем непосредственно к передаче объекта. Тут есть три варианта:
ObjectType myObject; foo(myObject);
ObjectType* myObject = new ObjectType(. ); foo(*myObject);`
ObjectType& myObject = otherObject; foo(myObject);
Как передать объект класса в функцию c
Аргументы, которые представляют переменные или константы, могут передаваться в функцию по значению (by value) и по ссылке (by reference).
При передаче аргументов по значению функция получает копию значения переменных и констант. Например:
#include void square(int); // прототип функции int main() < int n ; std::cout void square(int m) < m = m * m; // изменяем значение параметра std::cout Before square: n = 4 In square: m = 16 After square: n = 4
Почему так происходит? При компиляции функции для ее параметров выделяются отдельные участки памяти. При вызове функции вычисляются значения аргументов, которые передаются на место параметров. И затем значения аргументов заносятся в эти участки памяти. То есть функция манипулирует копиями значений объектов, а не самими объектами.
Передача параметров по ссылке
При передаче параметров по ссылке передается ссылка на объект, через которую мы можем манипулировать самим объектов, а не просто его значением. Так, перепишем предыдущий пример, используя передачу по ссылке:
#include void square(int&); // прототип функции int main() < int n ; std::cout void square(int& m) < m = m * m; // изменяем значение параметра std::cout по ссылке. Ссылочный параметр связывается непосредственно с объектом, поэтому через ссылку можно менять сам объект. То есть здесь при вызове функции параметрmв функцииsquareбудет представлять тот же объект, что и переменнаяnИ если мы скомпилируем и запустим программу, то результат будет иным:
Before square: n = 4 In square: m = 16 After square: n = 16Передача по ссылке позволяет возвратить из функции сразу несколько значений. Также передача параметров по ссылке является более эффективной при передаче очень больших объектов. Поскольку в этом случае не происходит копирования значений, а функция использует сам объект, а не его значение.
От передачи аргументов по ссылке следует отличать передачу ссылок в качестве аргументов:
#include void square(int); // прототип функции int main() < int n = 4; int &nRef = n; // ссылка на переменную n std::cout void square(int m) < m = m * m; // изменяем значение параметра std::cout Before square: n = 4 In square: m = 16 After square: n = 4Передача параметров по значению больше подходит для передачи в функцию небольших объектов, значения которых копируются в определенные участки памяти, которые потом использует функция.
Передача параметров по ссылке больше подходит для передачи в функцию больших объектов, в этом случае не нужно копировать все содержимое объекта в участок памяти, за счет чего увеличивается производительность программы.
Преобразования типов
Передача параметров по значению и по ссылке отличаются еще одним важным моментом. С++ может автоматически преобразовывать значения одних типов в другие, в том числе если подобные преобразования сопровождаются потерей точности (например, преобразование от типа double к типу int). Но при передаче параметров по ссылке неявные автоматические преобразования типов исключены. Так, рассмотрим пример:
#include void printVal(int); void printRef(int&); int main() < double value; printVal(value); // 3 printRef(value); // ! Ошибка > void printVal(int n) < std::cout void printRef(int& n)
Здесь определены две практически идентичные функции. Только функция printVal получает параметр по значению, а функция printRef - по ссылке. При вызове в обе функции передается число типа double . Но параметр обоих функций представляет тип int . И если при передаче по значению переданное число double успешно преобразуется в int (пусть и с потерей точности), то при передаче по ссылке мы столкнемся с ошибкой на этапе компиляции. Это еще одна причина, почему нередко рекомендуется передавать значения по ссылки - исключается вероятность предвиденных и иногда нежелательных преобразований типов.
Как передать метод класса в качестве колбэка?
Возможно ли в C++ передавать метод класса в качестве аргумента функции? Как правильно сделать то, что я пытаюсь сделать? (пример сферический в вакууме, поэтому счётчик должен оставаться атрибутом класса)
Всё это нужно для того, чтобы у колбека, передаваемого в качестве аргумента функции независимой библиотеке, оставался доступ к атрибутам объекта.
- Вопрос задан более трёх лет назад
- 1413 просмотров
c++ Передать метод одного класса в качестве параметра для метода другого кдасса
Здравствуйте. C++ . Есть две переменные, одна класса А, вторая класса B. Как бы передать нестатический метод 1 первого объекта в нестатический метод 2 второго объекта в качестве калбэк функции. При этом данная калбэк функция должна иметь доступ к членам своего объекта через this.
Пожалуйста, не отсылайте к гуглу. Перечитал несколько руководств, пока не получается.
rumgot ★★★★★
17.11.15 17:16:29 MSK

friend не вариант?
Kiborg ★★★
( 17.11.15 17:18:50 MSK )
лямбда, std::function (std::bind)
ossa ★★
( 17.11.15 17:19:02 MSK )
Gvidon ★★★★
( 17.11.15 17:19:27 MSK )
#include #include using std::cout; class A < public: void foo() < cout >; class B < public: using Cb = std::function; void go(Cb cb) < // some work cb(); >>; int main() < A a; B b; b.go([&a]() < a.foo(); >); >
anonymous
( 17.11.15 17:25:21 MSK )
не надо так делать
udhv ★
( 17.11.15 17:30:27 MSK )
Ответ на: комментарий от udhv 17.11.15 17:30:27 MSK
anonymous
( 17.11.15 17:32:37 MSK )
Ответ на: комментарий от udhv 17.11.15 17:30:27 MSK
rumgot
Касскажи свой кейс, скорее всего это нужно длелать по-другому.
Kroz ★★★★★
( 17.11.15 17:34:29 MSK )
Или указатель на член или универсальное решение в духе std::function + лямбда/std::bind.
anonymous
( 17.11.15 17:34:41 MSK )
Ответ на: комментарий от anonymous 17.11.15 17:32:37 MSK
Объясни зачем существуют private/protected, по ходу найдешь ответ на свой вопрос.
Kroz ★★★★★
( 17.11.15 17:35:42 MSK )
Ответ на: комментарий от Kroz 17.11.15 17:35:42 MSK
Как существование private/protected влияет на возможность передать в метод колбек?
При этом данная калбэк функция должна иметь доступ к членам своего объекта через this.
Как это нарушает private/protected?
anonymous
( 17.11.15 17:37:47 MSK )
Ответ на: комментарий от Kroz 17.11.15 17:35:42 MSK
Как этот пример нарушает приватность?
anonymous
( 17.11.15 17:38:43 MSK )
Ответ на: комментарий от Kroz 17.11.15 17:35:42 MSK
Колбэки существовали и использовались всегда, никакого отношения к private/protected они не имеют.
Gvidon ★★★★
( 17.11.15 17:38:45 MSK )
какой стандарт? Если до 11, то гугли fastdelegate, если после, то есть стандартные средства для этого.
gavlig ★★★
( 17.11.15 17:53:24 MSK )

http://www.boost.org/doc/libs/1_59_0/doc/html/signals2.html или libsigc++2 если нужно общее решение. И сигналы/слоты в Qt, разумеется.
asaw ★★★★★
( 17.11.15 17:56:23 MSK )
Таки есть указатели на методы класса. Почитай хотя бы тут https://rsdn.ru/article/cpp/fastdelegate.xml#EGD
AF ★★★
( 17.11.15 18:10:53 MSK )
Ответ на: комментарий от AF 17.11.15 18:10:53 MSK
Указатели на члены не содержат в себе объект, его придётся прокидывать отдельно, что не очень удобно.
Gvidon ★★★★
( 17.11.15 18:14:54 MSK )
boost::bind на стороне передающего коллбэк, boost::function на стороне получающего коллбэк
Manhunt ★★★★★
( 17.11.15 18:21:05 MSK )
Ответ на: комментарий от Gvidon 17.11.15 18:14:54 MSK
Методу класса, если он конечно не статический, полюбому нужен обьект. И как ты его не прячь за синтаксическим сахаром, суть от этого не поменяется!
AF ★★★
( 17.11.15 19:42:29 MSK )
Ответ на: комментарий от AF 17.11.15 19:42:29 MSK
И пишешь ты, наверное, в бинарных кодах. А чё, всё остальное — это синтаксический сахар, не меняющий сути.
Gvidon ★★★★
( 17.11.15 20:06:38 MSK )

Твоя задача решаема, но как тебе уже сказали, скорее всего, тебе нужно что-то другое.
Callback-и в C++ оказываются востребованы либо для связи с «необъектным» кодом, либо при кривой архитектуре. Подозреваю, что класс A может реализовать интерфейс I, и вот указатель на него можно передать в B.
hobbit ★★★★★
( 17.11.15 20:10:35 MSK )
Ответ на: комментарий от hobbit 17.11.15 20:10:35 MSK
Callback-и в C++ оказываются востребованы либо для связи с «необъектным» кодом, либо при кривой архитектуре.
Функторы, которые предлагается передавать в алгоритмы STL, как раз являют собой пример таких коллбэков. STL, может быть, и «необъектный», но вполне себе C++-ный.
Manhunt ★★★★★
( 17.11.15 22:15:27 MSK )
Ответ на: комментарий от AF 17.11.15 19:42:29 MSK
Методу класса, если он конечно не статический, полюбому нужен обьект. И как ты его не прячь за синтаксическим сахаром, суть от этого не поменяется!
За то поменяется объем портянки. Доля букв, посвященных бойлерплейту — сократится, а доля букв, посвященных смыслу вещей — возрастёт.
Manhunt ★★★★★
( 17.11.15 22:21:19 MSK )
Последнее исправление: Manhunt 17.11.15 22:21:27 MSK (всего исправлений: 1)

Как бы передать нестатический метод 1 первого объекта в нестатический метод 2 второго объекта в качестве калбэк функции
Ты хочешь неправильно.
no-such-file ★★★★★
( 18.11.15 05:28:17 MSK )
Ответ на: комментарий от Manhunt 17.11.15 22:21:19 MSK
Что хорошо опытному девелоперу на практике, то не всегда хорошо новичку в учении. ТС явно новичек и явно учится. Вот пусть и изучает основы, как все это работает.
AF ★★★
( 18.11.15 09:19:06 MSK )
Ответ на: комментарий от Kiborg 17.11.15 17:18:50 MSK

Ты еще волшебный каст с шаблоном предложи 🙂
slackwarrior ★★★★★
( 18.11.15 19:29:33 MSK )
Ответ на: комментарий от slackwarrior 18.11.15 19:29:33 MSK

Я малось нуб в плюсах, можно мне пример, чтоб я тоже шутку понял? 🙂
Kiborg ★★★
( 18.11.15 22:02:16 MSK )
Ответ на: комментарий от Kiborg 18.11.15 22:02:16 MSK

У Саттера были специально расписаны N-способов абузинга прав доступа с целью АЦЦКОГО ХОХОТА к членам класса http://www.gotw.ca/gotw/076.htm чтоб научить всех плохому типа как делать низязя. Еще причудливые люди, узнав про форварды с имплами, любят делать ссылки на экземпляр фасада из импла (потому что отказаться от имплов уже не могут) и прочие атататы 🙂 А потом они открывают для себя Александреску.
slackwarrior ★★★★★
( 18.11.15 23:53:09 MSK )
Ответ на: комментарий от hobbit 17.11.15 20:10:35 MSK
Callback-и в C++ оказываются востребованы либо для связи с «необъектным» кодом, либо при кривой архитектуре.
Совершенно необязательно. Очень часто бывают ситуации, когда сущность определяет, что произошло некоторое событие, но понятия не имеет что с ним дальше делать. В таких случаях удобно делегировать приняние решения какой-нибудь другой сущности (которая не всегда известна первой). Классический пример - кнопка пользовательского интерфейса. Может определить факт того, что ее нажали, но совершенно не знает, как и кто должен обрабатывать это событие. Можно конечно попробовать обмазаться паттерном «наблюдатель» или решать вопрос через наследование, но оба варианта ведут к чудовищной архитектуре. Гораздо правильнее тут использовать какой-нибудь другой callback-механизм (лично мне больше нравися концепция сигналов).
m0rph ★★★★★
( 19.11.15 00:48:11 MSK )
Последнее исправление: m0rph 19.11.15 00:49:15 MSK (всего исправлений: 1)