• 締切済み

継承でのエラーについて

現在C++を勉強しているのですが、教えてください。 サブクラス作成時のエラーなのです。 長いですがソース見てください。 勝手にインデントが無くなるので見にくいですが…。 #include <iostream> #include <string> using namespace std; class Hito{ private: string Name; public: Hito(string); //コンストラクタ void SelfIntro(); //自己紹介する }; //Hitoのコンストラクタ Hito::Hito(string str){ Name = str; } //自己紹介するメソッド void Hito::SelfIntro(){ cout << "私は、" << Name << " です。" << endl; } class Syusyo: public Hito{ private: int Ninki; public: Syusyo(string,int); void SayNinki(); }; //Syusyoのコンストラクタ Syusyo::Syusyo(string str, int year){ Hito(str); Ninki = year; } void Syusyo::SayNinki(){ cout << "私の任期は" << Ninki << "年です。" << endl; } int main(){ string str = "小泉アホの助"; int year = 5; Syusyo hito1(str,year); hito1.SelfIntro(); hito1.SayNinki(); return 0; } HitoクラスからSyusyoクラスを作っています。 そのSyusyoクラスのコンストラクタでエラーが出るのです。 内容は、 「デフォルトコンストラクタがありません。」 と言うものです。 参考書通りに Syusyo::Syusyo(string str, int year):Hito(str),Ninki(year){} とすればエラーにはなりません。 なぜ前出の文だとエラーになり、後出の文は大丈夫なのでしょうか? 文の表現が違うだけだと思うのですが…。

みんなの回答

回答No.5

C++では、断りがない限り、派生クラスのコンストラクタは、自分自身を実行する*前*に、基底クラスの、デフォルトコンストラクタを呼び出します。 これは、「引数のない」コンストラクタのことです。 ですから、この場合は、 Hito::Hito() というコンストラクタが必要です。 たとえば、 Hito::Hito() { name = ""; } があれば、 //Syusyoのコンストラクタ Syusyo::Syusyo(string str, int year){ name = str; Ninki = year; } は可能です。 ※つまり、名前無しで生成したインスタンスは無名にする。というのあれば、後で名前をつけることができる。 さらに、 Syusyo::Syusyo() の中で、 Hito(str); というのは、やめた方がいいでしょう。 これは、この場所で、(既に Hito クラスとしては構築が終わっているので)Hito() を構築できないためです。 今回の場合、Hito() クラスには、string を引数とするコンストラクタしかないために、基底クラスの構築のために、Hito() クラスに string を(Syusho クラスの構築に入る前に)渡す必要があるのです。 あと、メンバ変数に対しても、 Ninki(year) とするのと、コンストラクタの中で、 Niki = year; とするのは、少し違います。 前者は、初期化 後者は、代入です。調べてみるとおもしろいと思います。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.4

> 文の表現が違うだけだと思うのですが…。 処理内容の表現ではなく、文法上の構文が違います。 > 参考書通りに書けばエラーにならないのは分かっていますが、 > 「…:Hito(str)…」のように ":" を使いたくないのです。 ":"を使うのが、C++の初期化の文法です。 プログラミング言語の場合、文法に違反したソースはエラーになるのが普通です。 言語の文法に従いたくない理由は、なぜですか。 コンパイルを成功させたくないということですか。 > ":"を使わないで基底クラスのコンストラクタを実行させることは出来ないのでしょうか? 無理でしょう。 "自分のインスタンスの"基底クラスのコンストラクタを呼ぶのは、":"を使った文法になります。 それ以外の手順は…ハックですね。(むりやりdefineから別の手段まで 基底クラスのprivate以外のメンバ関数を呼び出すことはできますので、 setterを基底クラスに用意すればstrの代入はできますが、 初期化での自分のインスタンスに対する基底クラスのコンストラクタ呼び出しはできません。(初期化と代入は別のものです) # 十中八九意図と違うでしょうが、他のインスタンスであれば、 # コンストラクタの中で、基底クラスの変数を作るだけで # "基底クラスのコンストラクタが実行"されます。ただの言葉遊びですが。

回答No.3

> ":"を使わないで基底クラスのコンストラクタを実行させることは出来ないのでしょうか? おそらく無理。

回答No.2

> 文の表現が違うだけだと思うのですが…。 意味も変わります。 コンストラクタの { が始まるまでに、 基底クラスのコンストラクトは完了しています。

onara-pu-
質問者

お礼

回答ありがとうございます。 だいたいエラーになる理由は分かったのですが、どのように書けばエラーにならないのでしょうか? 参考書通りに書けばエラーにならないのは分かっていますが、「…:Hito(str)…」のように ":" を使いたくないのです。 ":"を使わないで基底クラスのコンストラクタを実行させることは出来ないのでしょうか?

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

コンストラクタを関数として呼び出したのでは駄目です。 > Syusyo::Syusyo(string str, int year){ > Hito(str); > Ninki = year; > } は < Syusyo::Syusyo(string str, int year):Hito(),Ninki(){ < Hito(str); < Ninki = year; < } と同じです。

onara-pu-
質問者

お礼

なるほど、確かにコンストラクタを関数として呼び出している文と同じですね。 こういう形にすればダメって事ですね。 回答ありがとうございます。

関連するQ&A

  • c++のvirtual関数および継承について

    以下のプログラムで間違っている部分が分かる方、ご指摘お願い致します。 私の稚拙な腕では、どこが間違っているのかさっぱり分かりません。 以下のプログラムは、クラスticketを継承して、airplaneTicket、cinemaTicketを作成し、チケットの情報を入力し、最後に出力するものです。コンパイルエラーの箇所はコメントアウトしておきました。メイン関数の中に計5箇所あります。 よろしくお願い致します。 #include<string> #include<iostream> #include<vector> using namespace std; class ticket{ public: string ID; string seat; int price; ticket(){ cout << "ticket default constructor" << endl; ID="not Known"; seat="not Known"; } ticket(string i, string t){ cout << "ticket parameter-constructor" << endl; ID=i; seat=t; } virtual void setPrice(int p)=0; void printInfo(){ cout << ID << " " << seat << endl; } }; class airplaneTicket: public ticket{ public: string flight; airplaneTicket(){ cout << "airplane default constructor" << endl; flight="not known yet"; } airplaneTicket(string i, string t, string f):ticket(i, t){ cout << "airplane parameter-constructor" << endl; flight=f; } virtual void setPrice(int p){ string type; cout << "enter class type: "; cin >> type; if(type=="business") price=p*2; else price=p; } void priceInfo(){ cout << ID << " " << seat << " " << price << " " << flight << endl; } }; class cinemaTicket: public ticket{ public: cinemaTicket(){ cout << "cinema default constructor" << endl; } cinemaTicket(string i, string t):ticket(i, t){ cout << "cinema parameter-constructor" << endl; } }; int main(){ ticket tList[100]; //error: invalid abstract type 'ticket' for 'tList' tList[0]=new airplaneTicket("239", "d34", "f345"); //error: no match for 'operator=' in 'tList[0] tList[1]=new airplaneTicket(); // error: no match for 'operator=' in 'tList[1] tList[2]=new cinemaTicket("245", "a23"); //error: cannot allocate an object of abstract type 'cinemaTicket' tList[3]=new cinemaTicket(); // error: cannot allocate an object of abstract type 'cinemaTicket for(int i=0;i<4; i++){ tList[i].printInfo(); } return 1; }

  • shared_ptr クラスについて

    shared_ptrクラスを使いたいのですが、使えません、どうしてでしょうか?ソースはこれです。 #include<iostream> #include <string> #include <fstream> #include<memory> using namespace std; class SMonster{ string name; int power; public: SMonster(); SMonster(int p); ~SMonster(){ }; void SetPower(int p); int GetPower(SMonster& t)const; void walk(const string& str); int GetPoint(void)const; }; class B {}; class D : public B {}; int main(void) { shared_ptr<D> sp0(new D); SMonster m(200); SMonster n(100); std::cout<<m.GetPower(m)<<std::endl; std::cout<<n.GetPower(n)<<std::endl; ShowWindow(10); }

  • 仮想関数と継承について

    #include <iostream> using namespace std; class AAA { public: virtual aaa() { cout <<"aaa(void)"<<endl;} }; class BBB : public AAA { public: virtual aaa(int a) { cout <<"aaa(int)"<<a<<endl;} }; int main() { BBB bbb; bbb.aaa();<--これがエラーになります。 return 0; } どうして、既定クラスの引数なしのaaa()はよぶことが できないのでしょうか?

  • switch文のエラーについて

    次のプログラムを実行したら slect.cpp:In member function `void select::setBlood(std::string)': slect.cpp:16:error: switch quantity not an integer が出ました。switch文の何が不完全ですか?教えてください。 #include<iostream> #include<string> using namespace std; class select { private: string blood; public: void setBlood(string b); void show(); }; void select::setBlood(string b){ blood=b; switch(b){ case 'A': cout<<"A is best"<<endl; break; case 'B': cout<<"B is best"<<endl; break; case 'AB': cout<<"AB is best"<<endl; break; case 'O': cout<<"O is best"<<endl; break; default: cout<<"crazy"<<endl; break; } } void select::show(){ cout<<"Your blood type is :"<<blood<<endl; } int main(){ string b; select Q; cout<<"Please Input your Blood type in A or B or AB or O:"<<endl; cin>>b; Q.setBlood(b); Q.show(); return 0; }

  • 質問です。。。

    いつもすみません。また質問させていただきます。 まずしたのプログラムを見てください・・・ #include <iostream> #include <string> using namespace std; int main() { string name; int tosi; cout << "こんにちは。私はコンピュータです。" <<endl; cout << "あなたの年齢を教えてください" <<endl; cin >> tosi; cout<<name<<"歳なんですか・・・老けてますね(笑)"<<endl; cout << "どこの学校ですか" <<endl; cin >> name; cout<<name<<"That's right!"<<endl; } このプログラムの8行目にあるint tosi;がありますよね。 この単語がなくても string name があったら12行目のプログラムができたのですが、どういうことなのでしょうか? 表現が一部変ですがよろしくお願いします。

  • vectorに格納されたオブジェクトの廃棄

    次のようなテストプログラムを作ってみました。 OSはVineです。 #include <iostream> #include <string> #include <vector> using namespace std; class Neko{ string name; public: Neko(){} Neko(string n):name(n){} void SetName(string n){name=n;} void Naku() const; }; void Neko::Naku() const{ cout << "名前は" << name << endl; } int main(){ int i; int num; string temp; vector <Neko> x; for(i=0;i<num;i++){ Neko *y=new Neko; x.push_back(*y); } for(i=0;i<num;i++){ cout << "名前を入力" << endl; cin >> temp; x[i].SetName(temp); } for(i=0;i<num;i++)x[i].Naku(); delete [] x;・・・※ } 廃棄(※のところ)するとき、これでは コンパイルエラーになってしまいます。 for文で回しても同じです。 どのように書けばよいのでしょうか? vectorにはポインタではなくオブジェクトが 入っていることに注意してください。

  • コンパイルエラー

    //test.cpp #include<iostream> #include<string> class test { string hoge; public: test(string str); void method() const; } 14行目  test::test(string str) : test(hoge){} void test::method() const { std::cout << "test" << std::endl; } int main() { string s; std::cout << "名前を入力してください。" << std::endl; std::cin >> s; test aaa(s); aaa.method(); } コンパイルしようとすると下記エラーになります。 エラー E2303 test.cpp 7: 型名が必要 エラー E2139 test.cpp 7: 宣言に ; がない エラー E2293 test.cpp 10: ) が必要 エラー E2147 test.cpp 14: 引数宣言は 'string' で始められない エラー E2111 test.cpp 14: ここでは型 'test' は定義できない エラー E2136 test.cpp 14: コンストラクタには戻り型は指定できない エラー E2316 test.cpp 14: 'test::test(int)' は 'test' のメンバーではない エラー E2451 test.cpp 22: 未定義のシンボル string(関数 main() ) エラー E2379 test.cpp 22: ステートメントにセミコロン(;)がない(関数 main() ) エラー E2451 test.cpp 24: 未定義のシンボル s(関数 main() ) *** 10 errors in Compile *** ■1.型名が必要 →string hoge;と宣言してる箇所でエラー発生。 …stringと宣言してるのになぜでしょうか… ■2.宣言に";"がない →string hoge;と宣言してる箇所でエラー発生。 …";"つけてるのですが… ■3.")"が必要 →test(string str);の行でエラー発生。 …")"はどこで必要なのでしょうか ■4.引数宣言はstringでははじめられない →test::test(string str) : test(hoge){}の行でエラー発生。 …C++って引数をstringで受け取れない…?どういうことでしょうか などなど疑問がいっぱいあるのですが、どこが間違っているのかよくわかりません…ご指導よろしくお願いします。

  • プログラムのどこがエラーか教えてください(C++)

    問題は、buildingという基本クラスを作って、建物の階数、部屋数、床の総面積を格納するクラスを作成し、次にhouseという派生クラスを作り、buildingを継承し、寝室数と、浴室数を格納するクラスで、officeという派生クラスを作り、これもbuildingを継承し、消火器台数と、電話台数を格納するクラスを作成し、それぞれの結果を出力せよ。っていう問題です。 下に僕が作成したプログラムを書きます。雑なので見にくいかもしれませんがお願いします。 #include <iostream> using namespace std; class building{ int Floor,Room,Area; public: building(int f,int r,int a){ Floor=f; Room=r; Area=a; } void get_FRA(int &f,int &r,int &a){ f=Floor; Room=r; Area=a; } }; class house:public building{ int Bedroom,Bathroom; public: house(int f,int r,int a,int Be,int Ba):building(f,r,a){ Bedroom=Be; Bathroom=Ba; } void Hshow(); }; class office:public building{ int FireExtinguisher,Telephone; public: office(int f,int r,int a,int fe,int t):building(f,r,a){ FireExtinguisher=fe; Telephone=t; } void Oshow(); }; void house::Hshow() { int x,y,z; get_FRA(x,y,z); cout << "階数:" << x << "階建て" << endl; cout << "部屋数:" << y << "室" << endl; cout << "床の総面積:" << z << "m2" << endl; cout << "寝室:" << Bedroom << "室" << endl; cout <<"浴室:" << Bathroom << "室" << endl; } void office::Oshow() { int x,y,z; get_FRA(x,y,z); cout << "階数:" << x << "階建て" << endl; cout << "部屋数:" << y << "室" << endl; cout << "床の総面積:" << z << "m2"<< endl; cout << "消火器の数:" << FireExtinguisher << "個" << endl; cout << "電話の数:" << Telephone << "個" << endl; } int main() { house H_ob(5,2,300,3,2); office O_ob(3,5,500,2,8); H_ob.Hshow(); O_ob.Oshow(); return 0; } あと、プログラムの処理結果を貼っておきます。 できれば、詳しく教えていただければ幸いです。

  • ofstream::getがおかしい!

    ofstream::getの動作がおかしいのです #include <string> #include <iostream> #include <fstream> using namespace std; void main(void) { ifstream ifs; ofstream ofs; string str; char c; str="abc"; cout<<"before str: "<<str<<endl<<endl; ofs.open("gomi");ofs<<str;ofs.close(); ifs.open("gomi");for(str="";ifs.eof()==0;str+=c)ifs.get(c);ifs.close(); cout<<"after str: "<<str<<endl<<endl; } の結果が before str: abc after str: abcc になります 最後のcは何でつくのでしょうか? 回避する方法を教えてください

  • このプログラムを...

    現在テスト用のプログラムを書いているのですが、なかなか動いてくれません。 ソース: #include <iostream> #include <iomanip> #include <string> using namespace std; struct MovieData { string title; string director; int year; int time; }; const int ARRAY_SIZE = 2; void showItem(MovieData[ARRAY_SIZE]); int main() { MovieData part[ARRAY_SIZE]; for (int cnt = 0; cnt < ARRAY_SIZE; cnt++) { cout << "Enter the movie's name: "; cin >> part[cnt].title; cout << "Enter the director's name: "; cin >> part[cnt].director; cout << "Enter the year of release: "; cin >> part[cnt].year; cout << "Enter the movie's running time: "; cin >> part[cnt].time; } showItem(part); return 0; } void showItem(MovieData part) { cout << fixed << showpoint << setprecision(2); for (int cnt2 = 0; cnt2 < ARRAY_SIZE; cnt2++) { cout << "Name of movie: " << part[cnt2].title << endl; cout << "Director: " << part[cnt2].director << endl; cout << "Year of released: " << part[cnt2].year << endl; cout << "Running time: " << part[cnt2].time << endl; } } どこが間違っているのでしょうか?宜しくお願いします。

専門家に質問してみよう