C++相談室2

このエントリーをはてなブックマークに追加
367デフォルトの名無しさん
>>366
この結果のどこがダサイですか?
Bの部分であるAをconstructする時に、Aに任せるのは当たり前では?
何か勘違いしてませんか?

$ cat virtual.c
#include <iostream>

using namespace std;

struct A {
A() { method(); }
virtual void method() { cout << "A's method() called" << endl; }
};

struct B : public A {
B() { method(); }
virtual void method() { cout << "B's method() called" << endl; }
};

int main(void) {
A a; B b;
return 0;
}
$ g++ test.c
$ ./a.out
A's method() called
A's method() called
B's method() called
$
368358じゃないよ:01/09/21 10:42
>>367
派生クラスによる追加部分が未構築な段階で、
基底クラスの構築子から派生クラスの仮想メソッドを呼べてしまうと、
その仮想メソッドが派生クラスの未構築なメンバをもしもアクセス
すると動作が異常になるので、言語仕様では安全サイドに振って
一律に派生クラス側のメソッドを呼べないようにしているわけだが、
コンパイラとリンカが神のごとく賢ければ、未構築なメンバを
アクセスする仮想メソッドの呼び出しに対してはエラーを、
さもなくば呼び出し可能としても良いわけで、>>358 はそれを
ダサいと言っているのであろう。
逆にプログラマ責任サイドに振って、派生クラスの仮想メソッド
を呼び出しOKにして、未構築なメンバをアクセスするような
仮想メソッドの場合は「未定義の動作」とする手もあったと思う。
C++の場合、この手の選択では「未定義の動作」とする場合が
多いのだが、そうしなかったのは仮想テーブルの設定を行う
実装が難しくなるからかな。
369javaの場合は:01/09/21 11:20
>>368 の続き
ちなみに、Java は基底クラスの構築子の中から、
派生クラスの仮想メソッドが呼べてしまう。

その時点では派生クラスで追加したフィールドは派生クラス
の構築子による設定前なので、デフォルトの0(null)が埋まっている。
C++のように「デフォルトは不定」ではないので、深刻な問題は起きない。
もちろん、0(null)がプログラマが意図した結果であるかどうかは別問題。

------------(インデントはスマン)
class A {
A() { v(); }
public void v() { System.out.println("A#v"); }
}
class B extends A {
String s;
B() { s="hello"; v(); }
public void v() { System.out.println("B#v s="+s); }
}

public class test {
public static void main(String[] argv) {
// A a = new A();
B b = new B();
}
}

$java test
B#v s=null
B#v s=hello
------------

C# ではどうなるのかな。