C++のクラスとコンストラクタに関する疑問

このQ&Aのポイント
  • C++のクラスでコンストラクタを指定できない理由とは?
  • デストラクタの場合は問題なく指定できるのに、なぜコンストラクタは指定できないのか
  • コンストラクタの指定に関する疑問を解決しましょう
回答を見る
  • ベストアンサー

C++のクラスについて

/*以下のコメントがある行では何故、コンストラクタ(class2::class2)を指定出来ないのですか? デストラクタ(class2::~class2)の場合も問題なくコンパイルが通り、実行できます (http://codepad.org/1oJkxjyZ の23行目) 開発環境 Windows XP SP3 コンパイラ:GCC 実行結果 class1のコンストラクタ class2のコンストラクタ aiueoの実行 class2のデストラクタ class1のデストラクタ */ #include<iostream> class class1; class class2; class class1{ public: class1(); ~class1(); private: class2*pointer; }; class class2{ public: class2(); ~class2(); void aiueo(); }; class1::class1(){ std::cout<<"class1のコンストラクタ"<<std::endl; pointer=new class2(); pointer->aiueo(); //aiueoを~class2に置き換えてもコンパイル出来るが、class2だとエラーが出る } class1::~class1(){ delete pointer; std::cout<<"class1のデストラクタ"<<std::endl; } class2::class2(){ std::cout<<"class2のコンストラクタ"<<std::endl; } class2::~class2(){ std::cout<<"class2のデストラクタ"<<std::endl; } void class2::aiueo(){ std::cout<<"aiueoの実行"<<std::endl; } int main(){ class1 test1; return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

んー...「(明示的に)メンバ関数のように呼び出すことはできない」と解釈できそうです。 言語規格(N3000:Working Draft, Standard for Programming Language C++) によると 12.1 Constructors Constructors do not have names. A special declarator syntax using an optional sequence of functionspecifiers followed by the constructor’s class name followed by a parameter list is used to declare or define the constructor. (中略) Because constructors do not have names, they are never found during name lookup; とあります。要するにコンストラクタは見てくれこそメンバ関数のようでありながら実は名前を持たない。 従って関数のように呼び出そうてしても(名前がないんだから)そんな関数は見つからない。 ...ってことのようです。 してみると僕とこの環境:Visual C++ 10で呼べてしまったのは厳密には誤りなのでしょうね。

vshdwn
質問者

お礼

そういうことだったんですか。 ありがとうございました

その他の回答 (2)

回答No.2

> main.cpp:23:22: error: cannot call constructor 'class2::class2' directly あー、処理系依存なのかしら。 それはそうと、何故にコンストラクタを明示的に呼び出したいんですか?

vshdwn
質問者

お礼

ありがとうございました

vshdwn
質問者

補足

特に理由はありません。 しいて言えば探究心で、出来るなら方法を、出来ないのなら理由を知りたいからです

回答No.1

pointer->class2::class2(); ではいかがです?

vshdwn
質問者

お礼

ありがとうございました

vshdwn
質問者

補足

回答ありがとうございます。 main.cpp: In constructor 'class1::class1()': main.cpp:23:22: error: cannot call constructor 'class2::class2' directly make: *** [main.exe] Error 1 とエラーが出てコンパイルできませんでした。

関連するQ&A

  • コンストラクタ・デストラクタ

    プログラミング言語はC++ C++を触り始めたばかりの素人です。 コンストラクタとデストラクタについて質問です。 下記に参考にしているウェブページから簡潔にしてコードを書いてみました。 コンストラクタ、デストラクタの中はそれぞれに、○○が呼び出されましたと書いてあるだけでよく分からなかったので別のウェブページを見たら コンストラクタは Sample::Sample(){ n=0; } みたいな例があったのですが、このように変数に予め何かの値を代入しておくという事で合ってますか? デストラクタは理解できていません。 下記の例では、どのような処理を書けばいいのでしょうか? #include<iostream> using namespace std; class Sample { private: int n; public: void Show(); Sample(); ~Sample(); }; void Sample::Show() { cout << n << endl; } Sample::Sample() { // n=0; std::cout << "コンストラクタが呼び出されました" << std::endl; } Sample::~Sample() { // どんな処理? std::cout << "デストラクタが呼び出されました" << endl; } main() { Sample sample; sample.Show(); return 0; } 実行結果 コンストラクタが呼び出されました 1     ←コンストラクタ関数内の//を削除で0になることは確認 デストラクタが呼び出されました

  • (C++)スマートポインタをメンバ変数で使いたい

    Viual Studio 2013を使ってC++のコードを書いています。 以下のコードで、new-deleteの クラス生成をスマートポインタで置き換えたいのですが、 うまくいきません。具体的には/* not smart */の部分を スマートポインタで置き換えたいが、C2059のエラーが出てきて コンパイルできないのが理解できていません。 どなたかわかる方教えていただければ幸いです。 よろしくお願いします。 // ----コードは以下---- #include <memory> #include <iostream> class Hoge { public: Hoge(){ std::cout << "constructed!" << std::endl; }; ~Hoge(){ std::cout << "destructed!" << std::endl; }; private: }; class Hogehoge { public: Hogehoge(){}; ~Hogehoge(){ delete test; /* not smart */}; private: // error C2059 w/ VS2013 // std::unique_ptr<Hoge> test(new Hoge); Hoge* test = new Hoge; /* not smart */ }; void main() { Hogehoge foo; }

  • C++の話です。

    C++の話です。 静的メンバ変数としてクラスを宣言した場合、デストラクタが呼ばれていないようなのですが、呼ぶ方法はありませんか? できれば「new」「delete」を使わずできると理想的です。 分かる方教えていただけると助かります。 以下、サンプルコードです。 「デストラクタが呼ばれました」と出力されない上、デバッガを使って試してみましたが、やはり呼ばれていないようです。 #include<iostream> class Test{   public:     ~Test(){       std::cout<<"デストラクタが呼ばれました"<<std::endl;     } }; class A{   private:     static Test T; }; int main(){   A a;   return 0; }

  • 【C++】アドレス演算子について質問です。

    アドレス演算子について質問です。 下記のように"&"を関数名の前に付けた場合下記のように出力されます。 &グローバルメソッド:002E1226 &クラス::メンバメソッド:1 1行目はグローバルメソッドなので実態が存在するのでメソッドのアドレスが表示されている。 2行目は実態が存在しないと思うのですが、あってますでしょうか? また、何故1が表示されてしまうのでしょうか? -------------------------------------------------------- #include "stdafx.h" #include <iostream> using namespace std; class Class1{ public: void f(){ return; } }; void Func1(){ return; } int main() { cout << "&グローバルメソッド:" << &Func1 <<endl; cout << "&クラス::メンバメソッド:"<< &Class1::f <<endl; getchar(); return 0; }

  • 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> class X { friend class Y; friend void f() { std::cout << "f()" << std::endl; } }; //class Y; //void f(); class Z { Y *ymem; void g() { ::f(); } }; int main() { ::f(); return 0; } C++プライマー第4版を読んでいます。511ページに上記のプログラムがあり、 「フレンドで導入されたクラスと関数(定義または宣言)は、すでに宣言されたものとして使うことができる。」 と説明されています。 しかし、g++(gcc4.4.1)でコンパイルするとエラーになります。コメント部分を外すと実行できます。 C++プライマーが正しいのか、gccが正しいのか、私が思い違いをしているのか、わかりません。 ご存知の方はいませんか。

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

    #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()はよぶことが できないのでしょうか?

  • C++のファイルの分割について教えてください。

    分割したプログラムの書き方を練習中なのですが、 下のようなプログラムを書いて、ビルドしようとしたら失敗します。 どこが悪いのか、教えていただけないでしょうか? (5)\test30\Debug\test30.exe : fatal error LNK1120: 外部参照 1 が未解決です。 1>test30 - エラー 2、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== //test30.cpp #include <iostream> #include "sub.h" int main(void) { std::cout<<"メインプログラムです。"<<std::endl; sub1(); sub2(); return 0; } ------------------------------------------------------------- //sub1.cpp #include <iostream> void sub1(void) { std::cout<<"サブ1です。"<<std::endl; } ------------------------------------------------------------- //sub2.cpp #include <iostream> void sub1(void) { std::cout<<"サブ2です。"<<std::endl; } --------------------------------------------------------------- //sub.h void sub1(void); void sub2(void);

  • Java→C++:オブジェクトの扱いに戸惑ってます

    C++を学び始めた者です。 これまでJavaを中心に開発していました。 オブジェクトの扱い方に関して若干戸惑っております。 下記のようなコードを実行したところ、問題なく動くことを確認しました。 しかし、Javaでは型の宣言はあくまで型を宣言しただけだったのに対し、 C++では宣言を行っただけでコンストラクタが動き、メンバ変数まで使えます。 下記のコードが動き実行結果も下記のようになることからその様に考えました。 これはJavaでいうところの型宣言の時点でC++はオブジェクトが作成されており、 実態が有ると考えて良いのでしょうか? しかし、new演算子はc++にも存在しているはずです。 上記の事を踏まえた上で Hoge hoge; とするのと  Hoge hoge = new Hoge(); とすることの違いを教えて下さい。 何か基本的なところで考えが誤っているのでしょうか? ----------------------------------------- #include "stdafx.h" #include <iostream> using namespace std; class Hoge { public: int hogeValue; Hoge():hogeValue(1000) { std::cout << "Hoge was constructed." << std::endl; PrintMessage(); getchar(); } public: void PrintMessage(){ std::cout << "PrintMessage was constructed. hogeValue = "<<hogeValue << std::endl; getchar(); } }; int main() { std::cout << "main() was called." << std::endl; getchar(); Hoge hoge; hoge.hogeValue=2000; hoge.PrintMessage(); } ---------------------------------------- 実行結果 main() was called. Hoge was constructed. PrintMessage was constructed. hogeValue = 1000 PrintMessage was constructed. hogeValue = 2000

  • 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; }

専門家に質問してみよう