Передача родительского объекта по ссылке - PullRequest
6 голосов
/ 23 ноября 2011

У меня есть этот код в библиотеке:

class Parent
{
    //some data and functions
};

void myfunc(Parent& ref);

, и я хочу сделать этот код в своем приложении:

class Child : public Parent
{
   // some other data and functions
   void dostuff()
   {
       myfunc(*this);
   }
};

Безопасно ли передать * это?(без нарезки, без копирования, ...) Лучше ли называть myfunc следующим образом:

myfunc( * ((Parent*)this) )

Обратите внимание, что я не контролирую, что происходит внутри myfunc, в некоторых случаях я не контролируюдаже знаю, что там происходит внутри.

Я много раз передавал указатель «родитель-по-указателю» и привык к нему, но никогда раньше не использовал указатель «передача-родитель-по-ссылке».

Ответы [ 2 ]

10 голосов
/ 23 ноября 2011

myfunc(*this) в порядке, если объявлено, что myfunc принимает ссылку - что это.

Это не будет копировать объект.Будет передана ссылка на оригинальный объект.Кроме того, он не будет разрезать объект.Ссылка будет иметь тип Base&, но объект, на который она ссылается, останется неизменным.

Точно так же вы знаете, если бы вы тогда вызывали полиморфные (например, virtual) методы этого Base&, полиморфизм все равно будет работать правильно и делать то, что вы ожидаете - как если бы вы вызывали через указатель.Другими словами:

Base& b = *derived;
b.SomeVirtualFoo();

... будет иметь тот же эффект, что и:

Base* b = derived;
b->SomeVirtualFoo();
5 голосов
/ 23 ноября 2011

Нет, первая версия верна:

 myfunc(*this);

Вторая версия, вероятно, будет работать в этом случае, но я не уверен, что она будет работать во всех случаях, если задействовано множественное наследование (так как вы используете приведение в стиле C). Я должен вытащить свой стандарт, чтобы посмотреть точное поведение C-Style.

Если это сработало, передавая указатель, тот же метод будет работать, если вы перейдете на использование ссылок.

Обновление:

Теперь, когда я прочитал стандарт, я вижу, что C-Cast будет делать правильные вещи (поскольку static_cast <> может использоваться для приведения иерархии классов от дочернего к родительскому).

5.4 Явное преобразование типов (нотация приведения)

4 Преобразования, выполненные
- const_cast (5.2.11),
- static_cast (5.2.9),
- static_cast, за которым следует const_cast,
- reinterpret_cast (5.2.10) или
- reinterpret_cast, за которым следует const_cast,

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

- указатель на объект типа производного класса или lvalue или rvalue типа производного класса может быть явно преобразован в указатель или ссылку на однозначный тип базового класса, соответственно;
- указатель на член типа производного класса может быть явно преобразован в указатель на член однозначного не виртуального типа базового класса;
- указатель на объект однозначного не виртуального типа базового класса, glvalue однозначного не виртуального типа базового класса или указатель на член однозначного не виртуального типа базового класса может быть явно преобразован в указатель, ссылка или указатель на член типа производного класса, соответственно.

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

...