web-dev-qa-db-fra.com

Initialisation d'une référence à member vers NULL en C++

Est-il possible d'initialiser un membre de référence à NULL en c ++?
J'essaie quelque chose comme ça: 

class BigClass
{
private:
  Object m_inner;
public:
  const Object& ReadOnly;
  BigClass() : ReadOnly(NULL)
  {
    Do stuff.
  }
};

Je sais que je peux le faire si j'initialise "ReadOnly" à une référence réelle d'un objet, mais lorsque je veux y mettre "NULL", j'obtiens l'erreur suivante: 

"ne peut pas convertir de 'int' en 'const Object &'

Comment puis-je résoudre ça?

19
Idov

Non, les références ne peuvent pas être NULL en C++.1

Les solutions possibles incluent:

  • en utilisant un pointeur au lieu d'une référence.
  • avoir une instance fictive Object qui peut être utilisée pour indiquer "aucun objet".

[1] Du norme C++ 11 :

[dcl.ref] [...] une référence null ne peut exister dans un programme bien défini, car le seul moyen de créer une telle référence serait de le lier à «l'objet» obtenu en déréférencant un null pointeur, qui provoque un comportement indéfini.

26
Oliver Charlesworth

Vous ne pouvez pas "résoudre" cela. Utilisez un pointeur si vous voulez que ce membre ne pointe pas vers rien.

Les références doivent être initialisées à un objet réel, elles ne peuvent pas "pointer nulle part".

10
Mat

Cela peut être fait, mais c’est presque certainement une extrêmement mauvaise idée . La façon de le faire est de déréférencer un pointeur NULL correctement typé, ce qui montre déjà que c'est une mauvaise idée: vous arrivez à un comportement indéfini à ce stade qui, cependant, tend généralement à «fonctionner».

En C++, les références sont censées toujours faire référence à un objet réel. Ceci diffère des autres langages de programmation où les "références" sont en réalité l'équivalent de pointers en C++ (généralement sans éléments comme l'arithmétique de pointeur). Ce que vous voulez probablement réellement (vous n'avez malheureusement pas dit ce que vous essayiez de faire, mais vous avez demandé une solution à un problème qui fait probablement partie d'une approche peu judicieuse): utilisez plutôt un pointeur:

Object const* const readOnly;
BigClass(): readOnly(0) {}
7
Dietmar Kühl

Utilisez un pointeur: - const Object * pReadOnly;

2
QuentinUK

C'est utile pour écrire des tests unitaires. C’est l’endroit seulement que cela devrait être fait, mais là, c’est très utile.

 Bar& bar(*static_cast<Bar*>(0));
 MockClass mock; // derives from RealClass
 mock.foo(bar);

Ici, je teste du code qui utilise MockClass, pas MockClass lui-même.

Ce n'est pas une panacée, mais cela peut aider. En outre, GoogleMock pourrait être votre ami si vous vous moquez de classes "concrètes".

struct Bar;
struct RealClass {
  int& x_;
  double& y_;
  RealClass(int& x, double& y) :x_(x), y_(y) {}
  virtual void foo(Bar&);
};
struct MockClass: public RealClass {
  MockClass(): RealClass(*(int*)0, *(double*)0) {}
  MOCK_METHOD1(foo, void(Bar&));
};
0
cdunn2001