web-dev-qa-db-fra.com

erreur: initialisation invalide de la référence de type 'int &' à partir de l'expression de type 'const int'

Il s'agit d'une question sans rapport avec le code dans cette question , concernant la fonction de modèle suivante.

template <class T>
class Object : public Container {
public:
    T& object;

    Object(const T& obj) : object(obj) {}
};

C'est le code qui appelle le constructeur:

template <class T>
void Array::add_element(const T& element)
{
    vec.Push_back(new Object<T>(element));
}

Ce code se compile très bien, mais dès que j'ajoute une ligne dans main qui l'appelle:

Array array;
int i = 3;
array.add_element(i);

Je reçois un avertissement du compilateur: error: invalid initialization of reference of type 'int&' from expression of type 'const int'.

De quoi s'agit-il? J'ai passé un int po. Ne devrait-il pas être automatiquement transformé en const int& pour moi? Pourquoi le compilateur se plaint-il?

12
Michael Dorst

obj est une référence const. object est une référence non constante.

Vous ne pouvez pas initialiser une référence non const à partir d'une référence const, car cela irait à l'encontre du but d'avoir une référence const en premier lieu.

Si vous voulez que votre instance de Object puisse modifier le int qui est passé à son constructeur, alors le constructeur doit prendre une référence non const. Si vous ne le faites pas, le membre de données doit être une référence const.

Dans tous les cas, vous enregistrez des problèmes pour vous-même si vous utilisez new pour allouer des objets qui ont des références en tant que membres de données. C'est votre problème pour vous assurer que vous supprimez le Object avant que i ne soit hors de portée (ou de toute façon, assurez-vous que le Object n'utilise pas son membre object après i est hors de portée.

13
Steve Jessop

Vous essayez d'affecter une référence const à une référence non const. Cela signifie que votre classe Object peut modifier le contenu de l'objet.

const int myConstNumber = 4;
Object<int> intObj(myConstNumber);

intObj.object = 3; // you have indirectly modified the value of myConstNumber

C++ ne vous laisse pas faire ça. Vous pouvez faire une copie de l'objet ou ajouter la constante à votre attribut.

template <class T>
class Object : public Container {
public:
    T object; // valid

ou

template <class T>
class Object : public Container {
public:
    const T& object; // valid

dans ce cas, vous ne pourrez pas modifier l'objet

8
ilmale