Je pratique mon OOP et j'ai les cours suivants: Point and Circle. Plus précisément, Circle a un point central et un rayon. Voici le code pertinent:
// Point.h
class Point
{
public:
Point(double x, double y);
double x() const;
double y() const;
std::string as_string() const;
private:
double x_coord;
double y_coord;
};
// Circle.h
class Circle
{
public:
Circle(const Point& center, double radius);
Point center() const;
double radius() const;
std::string as_string() const;
std::string equation() const;
private:
Point center_pt;
double radius_size;
};
// Circle.cpp
Circle::Circle(const Point& center, double radius)
{
center_pt = center;
radius_size = radius;
}
Cependant, lorsque j'essaie de compiler ce code, j'obtiens l'erreur suivante:
Circle.cpp: In constructor ‘Circle::Circle(const Point&, double)’:
Circle.cpp:3: error: no matching function for call to ‘Point::Point()’
Point.h:10: note: candidates are: Point::Point(double, double)
Point.h:8: note: Point::Point(const Point&)
Je ne suis pas sûr de savoir comment interpréter cette erreur. Est-ce que cela me dit que je dois fournir les paramètres x_coord et y_coord pour le paramètre Point dans mon constructeur Circle?
Le membre center_pt
est en cours d'initialisation par défaut et une telle opération appellera le constructeur par défaut sans arguments Point()
. Toutefois, cela n’est pas défini dans la classe Point
et vous donne donc l’erreur que vous avez.
Circle::Circle(const Point& center, double radius)
{
center_pt = center; //<-- this is an assignment
//default init has already occurred BEFORE this point
radius_size = radius;
}
Avant de pouvoir attribuer à center_pt
ici, vous devez attribuer un élément. Le compilateur essaie donc d’initialiser par défaut center_pt
pour vous avant d’essayer de faire l’affectation.
Si vous utilisez plutôt la liste liste d'initialisation des membres , vous pouvez éviter le problème de la construction par défaut suivie de l'affectation:
Circle::Circle(const Point& center, double radius):
center_pt(center),
radius_size(radius)
{
}
Lorsque vous créez une classe, vous mettez essentiellement de côté la mémoire pour stocker les différents membres de cette classe. Imaginez donc center_pt
et radius_size
comme des emplacements dans la mémoire dans lesquels ces valeurs sont stockées pour chaque instance de votre classe. Lorsque vous créez une classe, ces variables doivent recevoir certaines valeurs par défaut. Si vous ne spécifiez rien, vous obtenez les valeurs construites par défaut, quelles qu'elles soient. Vous pouvez attribuer ultérieurement des valeurs à ces emplacements, mais une initialisation aura toujours lieu au moment de la création de la classe. Si vous utilisez la liste d'initialisation, vous devez spécifier explicitement ce qui sera placé en mémoire la première fois.
En utilisant la liste d'initialisation des membres ici, vos membres sont correctement construits la première fois. Il a également l'avantage d'économiser certaines opérations inutiles.
Changer le constructeur de la manière suivante
Circle::Circle(const Point& center, double radius)
: center_pt( center ), radius_size( radius )
{
}
Le problème est que si vous n'appelez pas explicitement le constructeur avec les paramètres de la classe Point
, le compilateur essaie d'appeler le constructeur par défaut de la classe pour créer le membre de données center_pt
de la classe Circle avant de pouvoir affecter le point dans le corps du constructeur de classe Circle
. Mais vous n'avez pas défini le constructeur par défaut de la classe Point
et le compilateur a généré une erreur.
L’autre approche consiste en effet à définir le constructeur par défaut de la classe Point
qui initie par exemple un point avec des zéros.
Tenez compte du fait que, par la conception de la classe Point
, vous ne pouvez pas modifier les membres de données coord_x
et coord_y
d'un objet créé. Peut-être devriez-vous redéfinir la classe.
En effet, vous n'initialisez pas le membre dans la liste d'initialisation, mais vous l'affectez à celui-ci dans le corps. Par conséquent, il commence par le construire à l'aide du ctor par défaut, d'où la plainte de votre compilateur.
Envisagez de changer les choses pour:
// Circle.cpp
Circle::Circle(const Point& center, double radius) :
center_pt(center),
radius_size(radius)
{
}
Changement
Circle::Circle(const Point& center, double radius)
{
center_pt = center;
radius_size = radius;
}
à
Circle::Circle(const Point& center, double radius) : center_pt(center), radius_size(radius)
{
}
Alors qu'il utilise le constructeur que vous avez défini pour point. Aussi mieux pour le rayon aussi bien