私は私のOOPを実践しており、次のクラスがあります:ポイントとサークル。具体的には、サークルには中心ポイントと半径があります。関連するコードは次のとおりです。
// 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;
}
しかし、このコードをコンパイルしようとすると、次のエラーが発生します。
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&)
このエラーの解釈方法がわかりません。 CircleコンストラクターのPointパラメーターにx_coordとy_coordを指定する必要があることを示していますか?
メンバー_center_pt
_はデフォルトで初期化されており、そのような操作は引数なしのデフォルトコンストラクターPoint()
を呼び出します。ただし、これはPoint
クラスで定義されていないため、取得したエラーが表示されます。
_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;
}
_
ここで_center_pt
_に割り当てる前に、何かを割り当てる必要があります。したがって、コンパイラーは、割り当てを行う前に、まず_center_pt
_をデフォルトで初期化しようとします。
代わりに member initializer list を使用すると、デフォルトの構築とそれに続く割り当ての問題を回避できます。
_Circle::Circle(const Point& center, double radius):
center_pt(center),
radius_size(radius)
{
}
_
クラスを作成するときは、基本的に、そのクラス内のさまざまなメンバーを格納するためのメモリを確保します。したがって、クラスの各インスタンスに対してこれらの値が格納されるメモリ内の場所として_center_pt
_および_radius_size
_を想像してください。クラスを作成するとき、これらの変数にはいくつかのデフォルト値を指定する必要があります。何も指定しないと、デフォルトの構成値が取得されます。これらの場所に後で値を割り当てることができますが、クラスの作成時に常に初期化が行われます。イニシャライザリストを使用すると、最初にメモリに配置するものを明示的に指定できます。
ここでメンバー初期化子リストを使用することにより、メンバーは初めて適切に構築されます。また、不要な操作を節約できるという利点もあります。
コンストラクタを次のように変更します
Circle::Circle(const Point& center, double radius)
: center_pt( center ), radius_size( radius )
{
}
問題は、クラスPoint
のパラメーターを使用してコンストラクターを明示的に呼び出さない場合、コンパイラーは、クラスのデフォルトコンストラクターを呼び出して、クラスCircleのデータメンバーcenter_pt
を作成しようとすることです。クラスCircle
のコンストラクターの本体内のポイント。しかし、クラスPoint
のデフォルトコンストラクターを定義しておらず、コンパイラーがエラーを発行しました。
他のアプローチは確かに、クラスPoint
のデフォルトのコンストラクターを定義することです。たとえば、ゼロでポイントを初期化します。
クラスPoint
の設計により、作成されたオブジェクトのデータメンバーcoord_x
およびcoord_y
は変更できないことを考慮してください。クラスを再設計する必要があるかもしれません。
これは、初期化リストのメンバーを初期化するのではなく、本文でメンバーに割り当てるためです。したがって、最初にデフォルトのctorを使用してそれを構築しているため、コンパイラーの不満です。
次のものに変更することを検討してください:
// Circle.cpp
Circle::Circle(const Point& center, double radius) :
center_pt(center),
radius_size(radius)
{
}
Circleを構築する際に、デフォルトのコンストラクタを使用してPointを構築しようとしました:
Circle::Circle(const Point& center, double radius)
^
//...Calling default constructor...
...そしてassignedそれに値:
center_pt = center;
デフォルトのコンストラクターが存在しない場合、コンパイル時エラーが発生します。
2つのソリューションは次のとおりです。
1)メンバー初期化リストを使用してポイントを作成します。
Circle::Circle(const Point& center, double radius): center_pt(center),
radius_size(radius) {
}
2)ポイントのデフォルトコンストラクタを定義します。
Point::Point(){
}
この強調は上記の答えに欠けていたと思うので、私は主にこの質問に答えて強調をオプション2に配置します。デフォルトでは、ギブンズクラスのパラメーターリストにオブジェクトをデフォルトで作成し、後の段階でそれに値を割り当てる方が現実的です。これは、Qtフレームワークを使用するGUIプログラミングで少し発生します。
変化する
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)
{
}
そのため、ポイントに定義したコンストラクタを使用します。半径にも良い