C++初心者です。

とんちんかんな質問をしていたらすみません。

A_file.cppとB_file.cppというファイルがあり、それぞれの中でAとBというクラスを定義していると仮定します。
このとき、クラスAのメンバ変数としてBのインスタンスを持たせる場合、ポインタとして定義する方法(以下ソースのmember_pointer_B)と実体を定義する方法(以下ソースのmember_B)があると思いますが、これらの違い(なぜこのような2つの方法があるのか、そもそも言ってることがおかしいとか、使い方が違うとか、メリット・デメリットとか)を教えて下さい。

// ソース
class A {
int numberA;
int numberAA;
B* member_pointer_B; // ポインタの定義
B member_B; // 実体の定義
}

宜しくお願い致します。

回答の条件
  • 1人2回まで
  • 登録:2006/07/13 21:00:50
  • 終了:2006/07/20 21:05:03

回答(6件)

id:pernkopf No.1

pernkopf回答回数14ベストアンサー獲得回数12006/07/13 21:17:20

ポイント23pt

なかなかツボをついた、いい質問ですね。

普通は、実体だけでいいじゃん、なんでポインタなんてものがあるの?と思うでしょうね。

まず、ポインタの第一特徴は、コストが安い(CPUの使用時間が短い)という事です。

メモリ上のアドレスを差してる過ぎませんから、わずか数バイトです。

これを参照したり、コピーするのは、実体に同様の操作を加えるのに比べて非常に高速です。

また、メモリも食いません。

ですので、ツボを押さえて使えば、非常に高速で軽いプログラムを作る事が出来ます。

じゃあ、実体はいらないじゃん、そう思うかもしれません。

実際、ほとんどの高級言語では、実体化ポインタかはコンパイラや処理系の内部で管理されていて、プログラムの段階でポインタと実体を意識する必要があるのは、CやC++に特徴的です。

しかしながら、ポインタには、非常に大きな、本質的な問題があります。

それは、メモリ上の具体的なアドレスを差しているため、どのスコープからアクセスしても同じ実体を差してしまっているのです。

昔のBasicのように、小規模で、オブジェクト志向でない言語であれば、それほど問題にはなりませんが、C++のように、厳密にスコープが定義され、その中では他にどんな変数や関数を使っているか全く意識されずにコーディングされる言語では、あるポインタの指す実体が、いったいどこからアクセスされる可能性があるのか把握する事は、非常に困難です。

言い換えると、ポインタを使用する際は、メモリ管理を明示的に行わないと、メモリリークが発生したり、あるいはアクセス違反が容易に発生指趾、致命的なエラーを起こしやすいのです。

そのため、処理速度やメモリを必要としないプログラムでは、処理系やコンパイラがメモリ管理を行ってくれる実体をそのまま使うのが、上記のような矛盾やエラーを回避するためには安全です。

ただし、やっぱり重いプログラムになりやすいです。

ここら辺は、安全とスピードのトレードオフとなります。

http://www.stackasterisk.jp/tech/program/c01_05.jsp

id:konchan117

ありがとうございます。

実体での宣言と、ポインタでの宣言の違いが非常によくわかりました。

CとC++以外の言語を知らないので、勉強になりました。

ポインタにするか、実体にするかの判断基準がいまいちまだ理解できませんが、勉強します^^;

2006/07/14 00:56:34
id:kurukuru-neko No.2

kurukuru-neko回答回数1844ベストアンサー獲得回数1552006/07/13 21:18:46

ポイント23pt

電話機A,Bがあるとすると

ポインターは、電話機を区別するBの電話番号

実体とは、電話機Bそのもののこと

実際には、

ポインターには、クラスが保存されているアドレスが記録され。

クラスには実体データとしてのint、ポインター、

その他データが保存される。


http://www.ybi.co.jp/koike/src/c.htm

http://homepage2.nifty.com/well/Class.html

id:konchan117

ありがとうございます。

2006/07/14 00:59:20
id:mark_hk No.3

mark_hk回答回数31ベストアンサー獲得回数32006/07/13 21:20:58

ポイント22pt

○ポインタと実体を持つ違いですが、大いにあります。

  • ポインタ:アクセス用など所有していない場合
  • 実体:所有している場合(例えばパソコンクラスはメモリクラスを所有しているみたいな。わかりにくいか。)

これによってクラスのサイズが変わります。

※所有(含有)とアクセスの違いと捉えればいいのでは?

※メリット・デメリットというより構造上の違いなので、考えている構造にあわせれば良いのです。

id:konchan117

ありがとうございます。

構造上での違いなのですね。

>ポインタ:アクセス用など所有していない場合

>実体:所有している場合(例えばパソコンクラスはメモリクラスを所有しているみたいな。わかりにくいか。)

こちらの説明はわかりやすかったです。ただポインタと実体の違いについてはわかっているつもりですが、それをどのような場面で使用するか?っていう判断基準っていうのでしょうか。。。それがまだ明確ではないのです^^;

例えばポインタで宣言しておいて、後からnewで領域確保する・・・という行為(知人がソース中で使っていたのですが)がどのようなことを示すのか(最初から実体を宣言するのとの違い?)が曖昧というか・・・。

自分でも自分が何を言いたいのかわからなくなってきたような気も^^;

2006/07/14 01:02:31
id:mark_hk No.4

mark_hk回答回数31ベストアンサー獲得回数32006/07/14 09:39:48

ポイント22pt

>例えばポインタで宣言しておいて、後からnewで領域確保する・・・という行為(知人がソース中で使っていたのですが)がどのようなことを示すのか(最初から実体を宣言するのとの違い?)が曖昧というか・・・。


上の点については、

  1. ポインタが必然の場合
  2. 仮想関数が関係している場合

があるのかなと思います。


「ポインタが必然の場合」

使用しない場合はNULLポインタのままで、使用する場合に実体を作成するということをしている。(もしくは、宣言の時点では実体が決められない。プログラムの状況によって初めて決められるようになる。)


「仮想関数が関係している場合」

このURLを見てみると、Baseクラスのポインタの配列があるのですが、実体はBaseクラスから派生した、Point1クラスとPoint2クラスだったりするわけです。仮想関数であるshow_color関数を呼ぶことによってBaseクラスのポインタにアクセスしているのに、Point1クラスとPoint2クラスの関数を呼ぶことができます。


※説明が分かりづらいかもしれませんが、いかがでしょうか?

id:konchan117

ありがとうございます。

仮想関数・・・まだ勉強中なので、よくわかっていませんが、これから勉強します^^;

2006/07/14 11:13:03
id:pernkopf No.5

pernkopf回答回数14ベストアンサー獲得回数12006/07/14 16:38:53

ポイント10pt

ポインタと実体のメリットデメリットは、実際のところ自分である程度プログラミングしてみないと、体感しづらいと思います。

最初は自分で1から作るのではなくて、人のコードで理解できる部分を改変しながらその出力の変化を見ていくのがいいと思います。

最近のPCは非常に高速かつ大容量なので、ある程度大規模なコードでない土佐がわかりにくいかもしれませんが…。

言語の定義を全て理解しようとすると、頓座しやすいと思います。

特に、ポインタは、メモリを直接アセンブリ言語などで管理したことがないと、意味がわかりにくいです。

まずは、やってみる、のがよろしいかと。

id:studiokingyo No.6

d金魚回答回数47ベストアンサー獲得回数22006/07/18 11:51:07

ポイント10pt

こんにちは。私は主にC/C++でプログラムを組んでいる学生です。

最近はC言語ばかりでC++をあまりいじっていないのでまだ、述べていないメリットやデメリットがあるかもしれません。



ポインタの定義

メリット

・実体化のタイミングやインスタンスの種類をgoogle:ビジネスロジック側で決められる。

クラスAが実体化された(コンストラクタが実行された)際、まだクラスBは実体化されていないというメリットがあります。例えば、クラスBの実体化はクラスAの別関数で行う等、実体化に関する制御が可能という事です。

例えば、パラメーターによってインスタンスの種類を変えることが出来ます。

デメリット

・new と delete等のコードを書く量が増える。これによってバグが生まれる可能性がある。(こういうのを無くすためにtemplateを使った様々なテクニックがあるのですが・・・ スマートポインタとかシングルトンとか ですが、使用するにもいろいろと条件がありまして・・・ けっこう使いどころが難しいです。個人的にはスマートポインタはかなり汎用的なんでオススメです。google:boost shared_ptr等)




実体の定義

メリット

実体をコンストラクト時に生成するのでnew deleteが必要ない

デメリット

継承が沢山出来すぎると混乱してしまう

または継承では解決できないようなロジック的な問題を引き起こしてしまう。((すみません、この事例の記事を前に見たことあったんですけど忘れてしまいました。))




以下に各方法のメリット?をC++で載せておきます。

個人的にはclass D内のC::out();という所に思い入れがあります。

実はC++やっててかなり後になってから知ったことだったりします。

#include <iostream>

#include <windows.h>

using namespace std;

//以下ポインタのメリット


//仮想関数 持ち

class B{

public:

virtual ~B(){}

virtual void process() = 0;

};

class B0 : public B{

public:

B0(){}

virtual ~B0(){}

virtual void process(){

cout << "B0" << endl;

}

};

class B1 : public B{

public:

B1(){}

virtual ~B1(){}

virtual void process(){

cout << "B1" << endl;

}

};

class BDefault : public B{

public:

BDefault(){}

virtual ~BDefault(){}

virtual void process(){

cout << "BDefault" << endl;

}

};

class A{

B *bp;

public:

A(){

bp = NULL;

}

~A(){

clear();

}

//実体を削除する。

void clear(){

delete bp;

}

//実体を作る

void reset(int parameter){

clear();

switch(parameter){

case 0:

bp = new B0();

break;

case 1:

bp = new B1();

break;

default:

bp = new BDefault();

}

}

void b_process(){

if(bp)

bp->process();

else

cout << "bp NULL" << endl;

}

};


//以下実体のメリット

class C{

int mParam;

int mState;

public:

C(int param,int state){

mParam = param;

mState = state;

}

void out(){

cout << mParam << " " << mState << endl;

}

};

class D : public C{

public:

D(int param) : C(param,'D')

{

}

void out(){

C::out();

}

};

int main(){

int i;

//ポインタのメリット

A a;

a.b_process();

for(i=0;i<3;i++){

a.reset(i);

a.b_process();

}

//実体化のメリット

D d(32);

d.out();//32 68

system("PAUSE");

return 0;

}

ソースが上手く表示できなくてすみません。

コメントはまだありません

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません