Ошибка компилятора с функцией const - PullRequest
1 голос
/ 09 февраля 2009

Я не уверен, что мне не хватает чего-то простого. Но я не могу понять, почему компилятор генерирует ошибку для этого кода:

class A
{
};

class B
{
public:
    B();
    A* get() const;

private:
    A* m_p;
};

B::B()
{
    m_p = new A;
}

A* B::get() const
{
    //This is compiling fine
    return m_p;
}

class C
{
public:
    A* get() const;
private:
    A m_a;
};

A* C::get() const
{
   //Compiler generates an error for this. Why? 
    return &m_a;
}

РЕДАКТИРОВАТЬ: ошибка компилятора: ошибка C2440: «возврат»: невозможно преобразовать из «const class A *» в «класс A *». Преобразование теряет квалификаторы

Ответы [ 7 ]

13 голосов
/ 09 февраля 2009

const в сигнатуре функции сообщает компилятору, что члены объекта не могут быть изменены. Тем не менее, вы возвращаете не const указатель на участника, что позволяет нарушить это обещание.

В вашем классе B вы не делаете / нарушаете обещание, так как вы не возвращаете указатель на член, вы возвращаете его копию (и член оказывается указателем).

3 голосов
/ 09 февраля 2009

Это потому, что вы возвращаете неконстантный указатель на член из константной функции.

Первая часть работает, потому что вы возвращаете копию указателя на член, поэтому это не нарушает постоянство функции get:

class B
{
public:
    B();
    A* get() const;

private:
    A* m_p;
};

A* B::get() const
{
    //This is compiling fine
    return m_p;
}

Но следующий бит генерирует ошибку компиляции (в gcc 4)

testfile.cpp: 37: ошибка: неправильное преобразование из «const A *» в «A *»

Поскольку ваша функция const get предоставляет неконстантный доступ к m_a, возвращая неконстантный указатель на нее.

class C
{
public:
    A* get() const;
private:
    A m_a;
};

A* C::get() const
{
   //Compiler generates an error for this. Why?
    return &m_a;
}
1 голос
/ 09 февраля 2009

Поскольку возвращаемый указатель не является константой. Измените это на это:

class C
{
public:
    const A* get() const;
private:
    A m_a;
};

const A* C::get() const
{
    //Compiler generates an error for this. Why? 
    return &m_a;
}

Обратите внимание, что C :: get () теперь возвращает константный указатель на A.

0 голосов
/ 09 февраля 2009

В основном просто добавьте const впереди,

const A* C::get() const
{
   //Compiler generates an error for this. Why? 
    return &m_a;
}

Тогда, если вы хотите получить к нему доступ, в основном выполните:

C something;

const A* a = something.get();

Однако твоя программа имеет для меня очень мало смысла.

ИМО, наиболее разумно было бы сделать:

class A{
};

class C : public A
{
};

Таким образом, вам не нужно делать «get», который возвращает экземпляр A.

0 голосов
/ 09 февраля 2009
A* C::get() const
{
   //Compiler generates an error for this. Why? 
    return &m_a;
}

Поскольку get () является функцией const, компилятор обрабатывает все переменные-члены, которые он называет const. Когда вы берете адрес такого члена, вы получаете указатель на const. Но ваша функция возвращает неконстантный указатель. Вам нужно изменить код на

const A* C::get() const
{
    return &m_a;
}
0 голосов
/ 09 февраля 2009

Эта проблема может быть проиллюстрирована на более простом примере:

class MyClass {
public:
    int *get() const;
private:
    int value;
};

int *MyClass::get() const {
    return &value;
}

В MyClass::get() const, value имеет тип const int. Когда вы разыменовываете это, вы получаете const int *. Этот тип нельзя безопасно (неявно) привести к int *. Чтобы исправить вашу проблему, попросите get() return const int *.

0 голосов
/ 09 февраля 2009

Функции-члены, отмеченные const, не могут возвращать неконстантную ссылку или указатель на приватную переменную. Если бы компилятор позволил это, любой за пределами вашего класса мог бы изменить упомянутую приватную переменную, а спецификатор const в функции потерял бы значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...