Преобразовать «это» в ссылку на указатель - PullRequest
5 голосов
/ 28 апреля 2010

Допустим, у меня есть структура

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*&)

Итак, как мне преобразовать то, что очевидно const Foo* в 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
}

Ответы [ 4 ]

7 голосов
/ 28 апреля 2010

Вы не можете.

Во-первых, this не обязательно является const Foo *. this будет const Foo * - это метод const класса Foo. В неконстантном методе this это просто Foo *. (На самом деле ваше сообщение об ошибке упоминает Foo* const. Где вы видели const Foo *?)

Во-вторых, и что более важно, this не является lvalue. Вы не можете иметь указатель на this. Вы не можете иметь непостоянную ссылку на 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);
}
4 голосов
/ 28 апреля 2010

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

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;
0 голосов
/ 28 апреля 2010

Вы не.

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

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

0 голосов
/ 28 апреля 2010

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

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

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

Измените подпись функции на:

void do_baz(Foo* const& pFoo);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...