web-dev-qa-db-ja.com

クラスコンストラクターの呼び出しに対応する関数がありません

私は私の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を指定する必要があることを示していますか?

14
nonremovable

メンバー_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_を想像してください。クラスを作成するとき、これらの変数にはいくつかのデフォルト値を指定する必要があります。何も指定しないと、デフォルトの構成値が取得されます。これらの場所に後で値を割り当てることができますが、クラスの作成時に常に初期化が行われます。イニシャライザリストを使用すると、最初にメモリに配置するものを明示的に指定できます。

ここでメンバー初期化子リストを使用することにより、メンバーは初めて適切に構築されます。また、不要な操作を節約できるという利点もあります。

18
shuttle87

コンストラクタを次のように変更します

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は変更できないことを考慮してください。クラスを再設計する必要があるかもしれません。

6

これは、初期化リストのメンバーを初期化するのではなく、本文でメンバーに割り当てるためです。したがって、最初にデフォルトのctorを使用してそれを構築しているため、コンパイラーの不満です。

次のものに変更することを検討してください:

// Circle.cpp
Circle::Circle(const Point& center, double radius) :
    center_pt(center),
    radius_size(radius)
{

}
2
Ami Tavory

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プログラミングで少し発生します。

2
Dean P

変化する

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)
{
}

そのため、ポイントに定義したコンストラクタを使用します。半径にも良い

1
Ed Heal