Скажем, у меня есть структура
struct Foo {
void bar () {
do_baz(this);
}
/* See edit below
void do_baz(Foo*& pFoo) {
pFoo->p_sub_foo = new Foo; // for example
}
*/
Foo* p_sub_foo;
}
GCC говорит мне это
temp.cpp: In member function ‘void Foo::bar()’:
temp.cpp:3: error: no matching function for call to ‘Foo::do_baz(Foo* const)’
temp.cpp:5: note: candidates are: void Foo::do_baz(Foo*&)
Так, как делают я преобразовываю то, что, по-видимому, a const Foo*
к a Foo*&
?
Править: Я не использовал очень хороший пример. do_baz
должен читать
void do_baz(Foo*& pFoo) {
if (pFoo == NULL) {
pFoo = new Foo;
return;
}
//other stuff
do_baz(pFoo->p_sub_foo);
//more stuff
}
Вы не можете.
Во-первых, this
не обязательно является const Foo *
. this
будет const Foo *
будет константным методом класса Foo
. В неконстантном методе это
просто Foo *
. (На самом деле в вашем сообщении об ошибке упоминается Foo * const
. Где вы видели const Foo *
?)
Во-вторых, что более важно, это
не является lvalue. У вас не может быть указателя на это
. У вас не может быть непостоянной ссылки на this
. Единственное, что у вас может быть, - это постоянное уважение к this
, то есть ссылка типа Foo * const &
.
Это ( Foo * const &
) будет работать в вашем случае.
void do_baz(Foo* const& pFoo) {
pFoo->p_sub_foo = new Foo;
}
Но я не вижу во всем этом смысла. Просто объявите нормальный указатель Foo *
в качестве параметра для вашего метода do_baz
void do_baz(Foo* pFoo) {
pFoo->p_sub_foo = new Foo;
}
и получите тот же результат. Как вы думаете, для чего вам нужна эта ссылка?
EDIT : с учетом вашего редактирования, то, что вы пытаетесь сделать, не может быть выполнено с помощью одной функции do_baz
, поскольку при первом вызове вы потенциально (семантически) попытаетесь изменить this
, что невозможно (даже если модифицирующий код никогда не будет выполняться на практике).Хотите вы этого или нет, у вас не может быть неконстантной ссылки на this
, даже если вы не собираетесь ничего писать через него. Возможно, вам придется реализовать самый первый вызов с другой функцией
void do_baz(Foo*& pFoo) {
if (pFoo == NULL) {
pFoo = new Foo;
return;
}
//other stuff
do_baz(pFoo->p_sub_foo);
//more stuff
}
void do_baz_root(Foo* pFoo) {
assert(pFoo != NULL);
//other stuff
do_baz(pFoo->p_sub_foo);
//more stuff
}
, а затем сделать первый вызов как
void bar() {
do_baz_root(this);
}
Нет.
this
является Foo * const
, что означает, что это const
указатель на не const
Foo
. Ваша ссылка не является константой, поэтому правильным объявлением будет Foo * const &
.
Но в этом нет никакого смысла, так что не надо.
Дайте переменной имя, и тогда у вас будет тип ссылки на указатель:
void bar () { Foo* me = this; do_baz(me); }
Я также должен отметить, что ваша функция do_baz не использует тот факт, что ее параметр является ссылкой (вы присваиваете не самому указателю, а только тому, на что указывает указатель). Следовательно, действительно имеет смысл изменить тип параметра на Foo* вместо Foo*&, или сделать его Foo&, в этом случае вы будете использовать точку (.) вместо стрелки (->) при разыменовании члена параметра.
Редактировать
Ваша новая версия do_baz теперь использует тот факт, что параметр является ссылкой. Приведенное выше решение (простое использование именованного указателя) все еще будет работать для вашей новой версии проблемы. Тем не менее, я бы не советовал делать то, что вы делаете. Похоже, вы пытаетесь вставить элемент в конец связанного списка...
Во-первых, я бы посоветовал, если вы реализуете связный список, постоянно поддерживать не только указатель на первый узел списка, но и указатель на последний узел списка, чтобы вставка в конец списка могла выполняться в постоянном времени. Если, однако, такой возможности нет, я все же советую вам использовать итеративную, а не рекурсивную реализацию, поскольку она чище и проще. Это будет выглядеть так:
Foo* current=this; while (current->next != NULL){ current=current->next; } current->next = new Foo;
Ключевое слово this
не является l-значением, поэтому this
не может быть присвоено/изменено (независимо от того, является ли то, на что оно указывает, const
или нет). Другими словами, вы можете изменить то, на что указывает this
, но не можете изменить значение самого this
. Стандарт C++ 9.3.2 "Указатель this
":
В теле нестатической (9.3) функции-члена ключевое слово
this
является выражением без значения
Только ссылки const могут связываться с объектами без значения, поэтому, если вы хотите связать указатель this
со ссылкой, вам нужно связать его с Foo* const&
.
Измените сигнатуру функции на:
void do_baz(Foo* const& pFoo);