1. ホーム
  2. c++

[解決済み] クラス・コンストラクタの呼び出しに一致する関数がない

2022-02-08 10:45:50

質問

私はOOPの練習をしていて、以下のクラスを持っています。PointとCircleです。 具体的には、Circleは中心のPointと半径を持つ。 以下は関連するコードです。

// 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 を実行する前に、まずあなたのために。

その代わり、もしあなたが メンバー初期化リスト を使えば、デフォルトの構文に続いて代入が行われる問題を回避することができます。

Circle::Circle(const Point& center, double radius):
    center_pt(center),
    radius_size(radius)
{
}

クラスを作成するとき、基本的にそのクラス内のさまざまなメンバーを格納するためのメモリを確保することになります。つまり center_ptradius_size を、クラスのインスタンスごとにそれらの値が格納されるメモリ上の場所として使用します。クラスを作成する際には、これらの変数にデフォルト値を指定する必要があります。 もし何も指定しなかった場合は、デフォルトで作成された値を取得することになります。これらの変数には後から値を割り当てることもできますが、 クラスを作成する際には必ず何らかの初期化が行われます。イニシャライザーリストを使用すると、最初にメモリに配置される値を明示的に指定することができます。

ここでメンバ・イニシャライザ・リストを使用することで、メンバは最初に適切に構築されることになります。また、不要な操作を省くことができるというメリットもあります。