掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.28233

C…というかC++の継承についての質問です。
投稿者---GK(2006/09/21 17:03:58)


VisualC++.net 2003 Windows2000で
こんなプログラムを組んで実行してみた結果、mainのc1,c2,c3が指す先が異なるという事態が発生してしまいました。
class3のvirtual関数が問題なのでしょうか。

class class1
{
int test1;
};

class class2 : public class1
{
int test2;
};

class class3 : public class2
{
int test3;
virtual void v3(){}
};


int _tmain(int argc, TCHAR* argv[])
{
class3 *c=new class3();
class1 *c1=c;
class2 *c2=c;
class3 *c3=c;
return 0;
}

c 0x00374dc0
c1 0x00374dc4
c2 0x00374dc4
c3 0x00374dc0

ちなみにclass1に
virtual void v1(){}
を追加してみた結果、以下のようになりました。

c 0x00374dc0
c1 0x00374dc0
c2 0x00374dc0
c3 0x00374dc0

この現象について、どなたか説明できる方がいらっしゃいましたらお願いします。m(_ _)m


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:C…というかC++の継承についての質問です。 28235 shu 2006/09/21 17:36:26
<子記事> Re:C…というかC++の継承についての質問です。 28236 YuO 2006/09/21 18:01:30
<子記事> Re:C…というかC++の継承についての質問です。 28237 たかぎ 2006/09/21 18:10:24


No.28235

Re:C…というかC++の継承についての質問です。
投稿者---shu(2006/09/21 17:36:26)


参考になるかも

http://www.atmarkit.co.jp/fjava/rensai2/javaent04/javaent04.html


この投稿にコメントする

削除パスワード

No.28236

Re:C…というかC++の継承についての質問です。
投稿者---YuO(2006/09/21 18:01:30)


>VisualC++.net 2003 Windows2000で
>こんなプログラムを組んで実行してみた結果、mainのc1,c2,c3が指す先が異なるという事態が発生してしまいました。
>class3のvirtual関数が問題なのでしょうか。

何が問題なのかが全然解りません。
まぁ,class3にvtableの分が確保されたためでしょうが……。

そもそも,ポインタの値を表示した場合に,class1とclass2で異なっても何ら問題ないと思うのですが。
# たかだかポインタの値の表示結果に何でそこまでこだわるのかがわからない。



この投稿にコメントする

削除パスワード

No.28237

Re:C…というかC++の継承についての質問です。
投稿者---たかぎ(2006/09/21 18:10:24)
http://takagi.in/


ごく大雑把に説明します。

>class class1
>{
> int test1;
>};
>
>class class2 : public class1
>{
> int test2;
>};
>
>class class3 : public class2
>{
> int test3;
> virtual void v3(){}
>};

の部分をC言語に置き換えると、
struct class1
{
  int test1;
};

struct class2
{
  struct class1 __class1;
  int test2;
};

struct class3
{
  struct __class3_vtable
  {
    void (*v3)(void);
  } *__vtable;
  struct class2 __class2;
  int test3;
};
のようになります。
そして、
struct class3 *c = __new_class3();
struct class1 *c1 = &c->__class1;
struct class2 *c2 = &c->__class2;
struct class3 *c3 = c;
のように、基底クラスへのポインタでは、その基底クラスに相当する部分オブジェクトへのポインタを受けることになります。
結果として、class3の場合だけ、__vtableの分だけアドレスがずれることになります。

多くの処理系では、このような実装になっていますが、規格上それが要求されているわけではないので、常にこれが成り立つわけではありません。


この投稿にコメントする

削除パスワード

No.28239

Re:C…というかC++の継承についての質問です。
投稿者---GK(2006/09/22 09:34:30)


大雑把にといいながら詳しく説明してくださりありがとうございます。
なんとなく理解できてすっきりしました。内部ではそんなことが行われているんですね。

しかしclass1に
virtual void v1(){}
を追加したところ、全てのアドレスが等しくなったことについては未だ理解できません。
先ほど教えていただいたようにC言語に置き換えて考えてみましたがやはり分かりませんでした…



>そもそも,ポインタの値を表示した場合に,class1とclass2で異なっても何ら問題ないと思うのですが。
># たかだかポインタの値の表示結果に何でそこまでこだわるのかがわからない。

ツリーを構成するためのノードクラスを作成していまして、親ノードを削除すると子ノードもまとめて削除されるようにしているのですが、
そのノードクラスを継承して作られたクラスたちでツリーを構成する際に、ノードクラス内にある「親ノード設定関数」へ渡した子ノードアドレス値が変わってしまい、
親ノードからの自動削除時にエラーが発生してしまい困っていました。
アドレスが変わってしまうことが原因かな?と思ったので質問させていただきました。



この投稿にコメントする

削除パスワード

No.28240

Re:C…というかC++の継承についての質問です。
投稿者---たかぎ(2006/09/22 10:28:49)
http://takagi.in/


>しかしclass1に
>virtual void v1(){}
>を追加したところ、全てのアドレスが等しくなったことについては未だ理解できません。
struct class1
{
  struct __class1_vtable
  {
    void (*v1)(void);
  } *__vtable;
  int test1;
};

struct class2
{
  struct class1 __class1;
  int test2;
};

struct __class3_vtable
{
  struct __class1_vtable __vtable_class1;
  void (*v3)(void);
};

struct class3
{
  struct class2 __class2;
  int test3;
};

struct class3 *c = __new_class3();
ここで、c->__class2.__class1.__vtableには、__class3_vtableへのポインタが格納されていると考えてください。
つまり、
struct class3 *__new_class3(void)
{
  struct class3 *p = malloc(sizeof(struct class3));
  static struct __class3_vtable __vtable = {
    { &__class1_v1 },
    &__class3_v3,
  };
  p->__class2.__class1.__vtable = (struct __class1_vtable*)&__vtable;
  return p;
}
というイメージです。
__vtableが構造体だと分かりにくいのであれば、関数へのポインタ配列だと考えてもよいでしょう。

>そのノードクラスを継承して作られたクラスたちでツリーを構成する際に、ノードクラス内にある「親ノード設定関数」へ渡した子ノードアドレス値が変わってしまい、
>親ノードからの自動削除時にエラーが発生してしまい困っていました。

子ノードのアドレスをvoid*とかで渡していませんか?
あるいは、仮想デストラクタになっていないとか?



この投稿にコメントする

削除パスワード

No.28257

Re:C…というかC++の継承についての質問です。
投稿者---GK(2006/09/23 12:29:56)


返信送れましてすみません。
非常に細かく説明していただきありがとうございます。
なるほど…内部的にはそんな処理がされていたんですね。
勉強のためにも一度オブジェクト指向をC言語で書いてみようかと思います。

>子ノードのアドレスをvoid*とかで渡していませんか?
>あるいは、仮想デストラクタになっていないとか?
仮想デストラクタになっていませんでした。ご指摘ありがとうございます。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧