Ссылка на ошибку указателя: неконстантная ссылка lvalue const * FooBarClass не может привязываться к временному

ФуКласс.h:

class FooClass {
    .
    .
    .
    private:
        World *myWorld;
        const Player *&player;
    .
    .
    .
}

Фукласс.cpp:

FooClass::FooClass(..., World *w) : myWorld(w), player(w->getPlayer())
{
    .
    .
    .
}

Это вызывает следующую ошибку: Non-const lvalue reference to type 'const Player *' cannot bind to a temporary of type 'Player *'. Тем не менее, lvalue типа const Player * явно является константным lvalue...


person acannon828    schedule 11.09.2014    source источник
comment
const Player * — это тип, а не lvalue. Все, что возвращает w->getPlayer(), является Player *.   -  person chris    schedule 12.09.2014


Ответы (3)


Когда мы говорим о ссылках const, мы имеем в виду, что тип, к которому они относятся, — это const.

const Player *&player;

Эта декларация является ссылкой. Но является ли тип, к которому он относится, const? Нет, это не так! Он ссылается на указатель, но указатель не const. Просто бывает так, что указатель указывает на что-то, что равно const, но это не делает сам указатель const.

Чтобы привязать ссылку к временному значению, нужно сделать ссылку const. Итак, вам понадобится это:

const Player * const &player;

Однако я не могу себе представить, зачем вам это нужно. Зачем вам нужна ссылка на временное значение, возвращаемое getPlayer? Наверняка вам просто нужна копия указателя:

const Player* player;
person Joseph Mansfield    schedule 11.09.2014
comment
Если по какой-то причине объект Player in my World изменится, я бы хотел, чтобы элемент player отражал это изменение, поэтому мне понадобится ссылка, не так ли? - person acannon828; 12.09.2014
comment
@acannon828 Нет! Если вы копируете указатель, исходный указатель и копия содержат один и тот же адрес. Это означает, что они указывают на один и тот же объект. Независимо от того, как этот объект изменен, оба указателя увидят его. - person Joseph Mansfield; 12.09.2014
comment
Извините, я имел в виду, если бы объект Player in my World изменился на другой объект Player. - person acannon828; 12.09.2014
comment
@ acannon828 acannon828 Хорошо, но тогда вы будете изменять указатель, который является внутренним для World. Однако getPlayer возвращает копию этого указателя. Таким образом, ваша ссылка будет относиться к копии указателя, которая не будет изменена, если вы измените объект Player. Похоже, вы на самом деле хотите, чтобы getPlayer также возвращал ссылку, а затем сохранял не-const ссылку на этот возвращаемый указатель. Однако ссылки на указатели — это всегда дурной запах (сами указатели уже есть). - person Joseph Mansfield; 12.09.2014
comment
Да, в настоящее время нет возможности внешне изменить объект Player, но я просто пытаюсь продумать все возможные сценарии. Итак, вы бы просто использовали копию указателя? - person acannon828; 12.09.2014
comment
@ acannon828 acannon828 Если вам нужно увидеть, когда этот указатель изменяется, вам нужна ссылка на указатель, как вы пытались. Вам просто нужно изменить getPlayer, чтобы он также возвращал ссылку на указатель. В противном случае вы просто пытаетесь получить ссылку на копию, которую возвращает getPlayer, а это не то, что вам нужно. - person Joseph Mansfield; 12.09.2014
comment
Давайте продолжим обсуждение в чате. - person acannon828; 12.09.2014

Изменить это определение

private:
    World *myWorld;
    const Player *&player;

to

private:
    World *myWorld;
    const Player * const &player;

Вот пример

#include <iostream>

struct A
{
    A( const int *p ) : r( p ) {}
    const int * const &r;
};

int * foo()
{
    return new int( 10 );
}

int main() 
{

    A a( foo() );

    std::cout << *a.r << std::endl;

    delete a.r;
}   
person Vlad from Moscow    schedule 11.09.2014
comment
Теперь я получаю предупреждение Binding reference member 'player' to a temporary value. - person acannon828; 12.09.2014
comment
@ acannon828 Смотрите мой обновленный пример. Кажется, вы возвращаете указатель на локальную переменную. - person Vlad from Moscow; 12.09.2014
comment
Объект @ acannon828, на который указывает указатель w, может быть локальным объектом. Поэтому компилятор выдает предупреждение. Я показал вам пример, где используется оператор new. - person Vlad from Moscow; 12.09.2014

Вместо

const Player *&player;

тебе нужно

const Player * const &player;
               ^^^^^

чтобы иметь возможность привязать ссылку к временному значению.

Вы получаете предупреждение

Привязка ссылочного элемента 'player' к временному значению

потому что, по-видимому, w->getPlayer() возвращает временное значение.

person 4pie0    schedule 11.09.2014