Преобразуйте “это” в ссылку на указатель

Скажем, у меня есть структура

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
}
5
задан ThinkingStiff 30 June 2012 в 04:23
поделиться

4 ответа

Вы не можете.

Во-первых, 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);
}
7
ответ дан 13 December 2019 в 19:23
поделиться

Нет.

this является Foo * const , что означает, что это const указатель на не const Foo . Ваша ссылка не является константой, поэтому правильным объявлением будет Foo * const & .

Но в этом нет никакого смысла, так что не надо.

0
ответ дан 13 December 2019 в 19:23
поделиться

Дайте переменной имя, и тогда у вас будет тип ссылки на указатель:

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;
4
ответ дан 13 December 2019 в 19:23
поделиться

Ключевое слово this не является l-значением, поэтому this не может быть присвоено/изменено (независимо от того, является ли то, на что оно указывает, const или нет). Другими словами, вы можете изменить то, на что указывает this, но не можете изменить значение самого this. Стандарт C++ 9.3.2 "Указатель this":

В теле нестатической (9.3) функции-члена ключевое слово this является выражением без значения

Только ссылки const могут связываться с объектами без значения, поэтому, если вы хотите связать указатель this со ссылкой, вам нужно связать его с Foo* const&.

Измените сигнатуру функции на:

void do_baz(Foo* const& pFoo);
0
ответ дан 13 December 2019 в 19:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: