C++のコンストラクタで「no matching function for call to」というエラーになる場合の対処

C++のコンストラクタで「no matching function for call to」というエラーになる場合の対処

Posted at June 28,2017 12:03 AM
Tag:[C++]

C++のコンストラクタで「no matching function for call to」というエラーになる場合の対処について紹介します。

1.問題点

C++で下記の簡単なサンプルを作りました。

foo.h

class Foo {
private:
    int number;
public:
    Foo(int num);
    int print(void);
};

foo.cpp

#include "foo.h"
#include <iostream>
 
Foo::Foo(int num) {
    number = num;
}
 
int Foo::print(void) {
    std::cout << number << '\n';
}

test.cpp

#include "foo.h"
 
int main() {
    Foo f(100);
    f.print();
}

実行結果

% g++ foo.cpp test.cpp
% ./a.out
100

で、本題です。

上記のサンプルに、Fooクラスを継承するBarクラスを追加してみました。

bar.h

#include "foo.h"
 
class Bar: public Foo {
public:
    Bar(int num);
    int print(void);
};

bar.cpp

#include "bar.h"
#include <iostream>
 
Bar::Bar(int num) {
    number = num;
}
 
int Bar::print(void) {
    std::cout << number << '\n';
}

foo.hのメンバ変数numberは子クラスからもアクセスするのでprivateからprotectedに変更。

foo.h

class Foo {
protected:
    int number;
public:
    Foo(int num);
    int print(void);
};

test.cppからのインクルードやmain()のクラス型はFooからBarにそれぞれ変更します。

test.cpp

#include "bar.h"
 
int main() {
    Bar f(100);
    f.print();
}

ビルドを実行すると、コンパイルで「no matching function for call to 'Foo::Foo()'」というエラーが発生します。

% g++ foo.cpp bar.cpp test.cpp
bar.cpp: コンストラクタ 'Bar::Bar(int)' 内:
bar.cpp:4:17: エラー: no matching function for call to 'Foo::Foo()'
Bar::Bar(int num) {
^

2.原因

コンパイルエラーの原因はつぎのいずれかになります。

  • Fooクラスに引数が空のコンストラクタが定義されていない
  • Barクラスのコンストラクタに継承するコンストラクタが定義されていない

ひとつめの原因の解説ですが、C++の子クラスでコンストラクタを起動すると、先に親のコンストラクタが呼ばれるようになっています。

前述のBarクラスのコンストラクタ定義では、Barのコンストラクタ起動前に、親クラスの引数なしのコンストラクタが起動されるのですが、Fooクラスには引数なしのコンストラクタが定義されていないため、「no matching function for call to 'Foo::Foo()'(Foo::Foo()の関数呼び出しが正常に行えない)」というエラーに遭遇してしまったようです。

あるいはBarクラスのコンストラクタを変更して、継承する親コンストラクタを定義すれば、親クラスに引数なしのコンストラクタを定義する必要はありません。

ということで、それぞれの原因に対する対処方法を下記に示します。

ちなみにC++にはJava言語の「super」に該当するものはありません。

3.対処方法1:Fooクラスに引数が空のコンストラクタを定義

ひとつめの対処方法は、赤字で示すように、Fooクラスに引数が空のコンストラクタを定義することです。

foo.h

class Foo {
protected:
    int number;
public:
    Foo();
    Foo(int num);
    int print(void);
};

foo.cpp

#include "foo.h"
#include <iostream>
 
Foo::Foo() {}
 
Foo::Foo(int num) {
    number = num;
}
 
int Foo::print(void) {
    std::cout << number << '\n';
}

実行結果

% g++ foo.cpp bar.cpp test.cpp
% ./a.out
100

4.対処方法2:Barクラスのコンストラクタに継承するコンストラクタを定義

もうひとつの対処方法は、Barクラスのコンストラクタ定義に、赤字で示すように継承するコンストラクタを定義することです。

bar.cpp

#include "bar.h"
#include <iostream>
 
Bar::Bar(int num): Foo(num) {
    number = num;
}
 
int Bar::print(void) {
    std::cout << number << '\n';
}

実行結果

% g++ foo.cpp bar.cpp test.cpp
% ./a.out
100

継承するコンストラクタのパラメータは変数名のみ記述すればOKです。型の記述は必要ありません。

関連記事
トラックバックURL


コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)