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

このQ&Aのポイント
  • Java→C++のオブジェクトの扱い方について、戸惑っています。
  • C++ではオブジェクトを宣言するだけでコンストラクタが動き、メンバ変数を使うことができます。
  • new演算子の違いやコードの実行結果についても教えてください。
回答を見る
  • ベストアンサー

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

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

  • ベストアンサー
  • hitomura
  • ベストアンサー率48% (325/664)
回答No.2

Java の型にはプリミティブ型と参照型がある、それは理解してますよね? C++ の場合、型名だけを書いた場合、たとえクラスであってもすべてプリミティブ型のようにふるまいます。 ですから、  Hoge hoge; となっている時点で  int i; と同様に変数の宣言と同時にその値の生成が行われ、その過程でコンストラクタが呼ばれます。 C++ で Java の参照型を表すものはポインタになります。 たとえば、  Hoge* p_hoge = new Hoge(); という感じで Java の  Hoge hoge = new Hoge(); と同じに……なったらいいんだけどねぇ。 このポインタというもの、Java の参照と比べて厄介です。というか、C/C++ のポインタの厄介な部分を全部オミットしたものが Java の参照です。 簡単に言えば、Java ではガーベージコレクタに任せていたメモリ管理を自分でやらなくてはならないという事です。これがどれだけ大変かというと、ポインタだけで本が一冊書けるくらい大変です。 Java の参照型の感覚でポインタを扱ったら「アイエェェェ メモリーリーク? メモリーリークナンデ?」か「一般保護違反なんて Java のテストに出ないよお…」となること確実です。 どうしても Java と同じ感覚でオブジェクトを扱いたいのであればスマートポインタというものを調べてみてください。 でも、メモリ管理を自分でやらなくてはならないということは逆にメモリ解放のタイミングを自分で決められるという事でもあります。それを利用すれば Java よりも効率的なプログラムを書くこともできます。 また、C++ では  Hoge hoge; の方もいろいろと便利なのでポインタを使って new するのと同じくらい使います。 特に、RAII と呼ばれるテクニックでは、上記のように記述することでブロックを抜けるときに確実にデストラクタが呼ばれるという性質を利用しています。 http://ja.wikipedia.org/wiki/RAII ……finally? 知らない子ですね。というか、インスタンス破棄のタイミングがガーベージコレクション任せでプログラマ自身では確実に制御できない Java では finally は必要でしょう。しかし上記のテクニックが使える C++ では finally のような構文は特に必要がないという趣旨のことを C++ の設計者は『C++ の設計と進化』という本の中で書いています(16.5節)。厚いし難しい本なので万人向けではありませんが、C++ という言語がどのように生み出されたか、C++ の構文選択の際どのような選択がされたかを知る上で重要な本ですので、C++ を深く知りたいのであれば読んでおいた方がいい本です。

その他の回答 (1)

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.3

何だか変数の宣言とインスタンスの生成がごっちゃになられているような。 >しかし、Javaでは型の宣言はあくまで型を宣言しただけだったのに対し、 ここでいわれている「型」というのは「クラス」の事だと思いますが、 Javaでいう「クラスの宣言」は public class AAA { ... } とクラスを書く事ですけど。 ちなみにC++では「宣言」ではなく「定義」になります。 >Hoge hoge; とするのと Javaではhogeという名前の変数(インスタンスの入れ物)を用意しているだけですが C++ではhogeという名前の変数であり、その変数はインスタンス自身です。 見た目は同じ書き方ですが意味が違うんです。 C++でJavaと同じような事をするなら Hoge *hoge; になります。 >Hoge hoge = new Hoge(); C++だとエラー。

関連するQ&A

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

  • 添字演算子

    #include <iostream> class hoge{ private: int a; public: hoge(){ a = 0; } int operator+(int fuga){ a = a + fuga; return a; } int operator[](int fuga){ return 1; } }; int main(){ hoge* p; p = new hoge; std::cout << ((*p) + 5) << std::endl; std::cout << ((*p)[1] ) << std::endl; // 5 // 1 // std::cout << ((*p) [] 1); エラーです。何故ですか? }

  • 警告「代入される前に使われている」を出す方法

    bccで以下のコードをコンパイルすると。 「'i' は、おそらく値が代入される前に使われている」 と警告が出ますが、 「'h' は、おそらく値が代入される前に使われている」 とは警告を出してくれません。 警告を出す方法ってないでしょうか? Hogeメンバに bool 型の初期化フラグでも実装しようかな・・・。 #include <iostream> class Hoge { public: Hoge(){ } Hoge( int i ){ t = i; } operator int(){ return t; } int t; }; int main() { int i; Hoge h; std::cout << i << std::endl; std::cout << h << std::endl; return 0; }

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

  • C++について。

    現在”猫でもわかるプログラミング”のC++編をSDKと共に勉強している身です。 現在第22章、第23章を勉強中です。 22章 http://www.kumei.ne.jp/c_lang/cpp/cpp_22.htm 23章 http://www.kumei.ne.jp/c_lang/cpp/cpp_23.htm 作業環境はVisual Studio 2005.net C++です 22章でのプログラムを作成し、実行した結果エラーが出てしまいました。 ソースです #include <iostream> class xy_position { int x; int y; public: xy_position(int x = 0, int y = 0){ xy_position::x = x; xy_position::y = y; } int X() const {return x;} int Y() const {return y;} }; ostream& operator << (ostream& o, const xy_position& p) { return o << "(" << p.X() << "," << p.Y() << ")"; } int main(void) { xy_position a(50, 60), b; std::cout << a << b << std::endl; return 0; } (17):error C2143: 構文エラー : ';' が '&' の前にありません。 (17):error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません (17):error C2065: 'o' : 定義されていない識別子です。 (17):error C2059: 構文エラー : 'const' (18):error C2143: 構文エラー : ';' が '{' の前にありません。 (18):error C2447: '{' : 対応する関数ヘッダーがありません (旧形式の仮引数リスト?) (26):error C2679: 二項演算子 '<<' : 型 'xy_position' の右オペランドを扱う演算子が見つかりません (または変換できません)。 このようなエラーが出てしまいました。 もちろんソースは全て同様に書いています。 この”猫でも”で使用しているコンパイラと異なるために出たエラーでしょうか? それに単に cout << のように記述するとエラーが出てしまい、 std::cout << のように記述しなければ通りません。 また、エラーとは別の質問になってしまいますが、プログラム中に int X() const {return x;} という記述がありますが、このconstの意味が分かりません。 単純に return x が変更不可能という意味でしょうか? 次に23章についての質問です。 ここでもソースは同じなのに以下のようなエラーが出てしまいます。 ソースです。 #include <iostream> int main(void) { int x=10, y=15, z=20; std::cout << "16進表示" << std::endl; std::cout.setf(ios::hex); std::cout << x << std::endl; std::cout << y << std::endl; std::cout << z << std::endl; std::cout.unsetf(iostream::hex); std::cout << "8進数" << std::endl; std::cout.setf(ios::oct); std::cout << x << std::endl; std::cout << y << std::endl; std::cout << z << std::endl; return 0; } (8):error C2653: 'ios' : 識別子がクラス名でも名前空間名でもありません。 (8):error C2065: 'hex' : 定義されていない識別子です。 (13):error C2653: 'iostream' : 識別子がクラス名でも名前空間名でもありません。 (15):error C2653: 'ios' : 識別子がクラス名でも名前空間名でもありません。 (15):error C2065: 'oct' : 定義されていない識別子です。 これも何か設定をしなければいけないのでしょうか? なにぶんC++は・・・というかオブジェクト指向の言語は初心者なもので疑問も多いですorz

  • 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++ 静的クラスの役割が分からない

    こんばんは。 C++で静的オブジェクトがなんなのか試しにプログラミングしているんですが どんな役割があるのか試してもよく分かりません。 static class HOGE { public: int *hoge; private: int value[2]; char moji[6]; public: HOGE() { cout << "HOGE\n"; } void MOJI() { strcpy(moji, "MOJI\n"); } void TEST() { cout << "moji = " << moji << endl; } static void staticMOJI() { } }sObj; sObjからは静的メンバ関数と静的メンバ変数は呼び出せるようです。他は呼び出せません。 そのようにするためにstatic宣言をするものなのでしょうか? このsObjからメンバ変数(*hoge)を呼び出すことは無理なんでしょうか?

  • 変数の隠蔽とスコープ

    いつまでも初心者のままじゃ駄目だなあと思い, 用事のついでに本屋まで行って 評価が高いらしい http://www.amazon.co.jp/exec/obidos/ASIN/4797328541/Lvdrfree-22?dev-t=D1KDF7Q74DD3A2%26camp=2025%26link_code=xm2 を100ページほど立ち読みしてみた。(買ってません) で、まあ内容を理解できているかは別として 可視性とアクセス制御という話があって Java や C#の時の知識から 以下のコードの出力結果は一応理解できます。 折角なので 質問もコードの中に書いてみました。 ========================== #include <iostream> int a = 5; class fuga{ public: int a; fuga(){ a = 3; } }; class hoge : fuga{ //実際の書籍では public fugaだったような public: void printa(){ std::cout << a << std::endl; //コンパイル通っちゃったけど,ここからグローバル変数a(==5)にアクセスする方法はあるの? } }; int main(){ hoge* p = new hoge; p->printa(); std::cout << a << std::endl; delete p; // 3 // 5 }

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

  • c++プログラム。どこがだめか教えて欲しいです。

    以下のプログラムにおいて、後者のコンパイルが通りません。 違いは、クラス:Kurasu のコンストラクタに引数があるかないかで、 全部で3行違います。 後者のどこが問題か指摘して欲しいです。(さっぱりわからない…。) 試した環境は、 Visual C++ 2010 Express + インストーラー配布のboostと、 Eclipse 3.5.2 Galileo Windows 32bit ベース / Pleiades All in One 3.5.2.20100226 のUltimate+←を使ってソースをビルドしたboostです。 boostのバージョンは、1.46.1です。 -------------------------------------------------- #include <iostream> #include <boost/thread.hpp> using namespace std; using namespace boost; class Kurasu { public: Kurasu(int ababa){}; void run(){ for( int i = 0; i < 10; i++ ){ cout <<"foo "; } }; }; int main() { cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! Kurasu hoge(1); Kurasu piyo(2); thread thr_hoge( &Kurasu::run, &hoge ); thread thr_piyo( &Kurasu::run, &piyo ); thr_hoge.join(); thr_piyo.join(); return 0; } -------------------------------------------------- #include <iostream> #include <boost/thread.hpp> using namespace std; using namespace boost; class Kurasu { public: Kurasu(){}; void run(){ for( int i = 0; i < 10; i++ ){ cout <<"foo "; } }; }; int main() { cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! Kurasu hoge(); Kurasu piyo(); thread thr_hoge( &Kurasu::run, &hoge ); thread thr_piyo( &Kurasu::run, &piyo ); thr_hoge.join(); thr_piyo.join(); return 0; } --------------------------------------------------

専門家に質問してみよう