3

内部にクラスが定義されたスーパークラスがあります。お気に入り:

class A {
 public:
  class B {public: bool value;};

  A() {
      DoStuff(b_);
  }
  B b_;
 private:
  virtual void DoStuffImpl(B& b) = 0;
  void DoStuff(B& b) { return DoStuffImpl(b); }
};

class X : public A {
  // ...
 private:
  virtual void DoStuffImpl(B& b);
  void UseBForSomethingElse(B& b);
};

void X::DoStuffImpl(B& b) {
    UseBForSomethingElse(b);
}

void X::UseBForSomethingElse(B& b) {
    b.value = true;
}

int main(){
    X x;
    return x.b_.value;
}

DoStuffImpl()私のコンパイラはそれをうまく理解しているようです。しかし、 を追加UseBForSomethingElse()すると、コンパイラはBクラスの定義を見つけることができませんでした。を実行してさらに特定しようとしましたbool UseBForSomethingElse(A::B& b)。これはコンパイルされましたが、リンク中に失敗しました。

parent を正しく指定するにはどうすればよいBですか? 仮想関数では機能するのに、他の機能では機能しないのはなぜですか?

4

2 に答える 2

1

OP編集に基づく編集:

ideoneがランタイムエラーがあると言う理由は、mainから1を返しているためです。からのゼロ以外の戻り値はmain、実行の失敗と見なされます。return !x.b_.value;ideoneに戻るだけを変更すると、期待どおりに成功が報告されます。

元の答え:

void UseBForSomethingElse(const B& b) {
    b.value = true;
}

定数参照()に割り当てることはできないbので、それは確かに問題の1つです。

UseBForSomethingElseまた、の定義を修飾しなかったX::ため、コンパイラはそれをのスコープに入れずX、親のネストされたクラスを認識できなくなりました。

于 2012-11-09T17:00:27.803 に答える
1

更新された投稿は、UseBForSomethingElse() を適切に修飾していません。

void UseBForSomethingElse(const B& b)

する必要があります

void X::UseBForSomethingElse(const B& b)

これが修正されても、まだ問題があります (これを間違えた場合は天国が助けてくれます)。

派生クラスが構築を完了することなく、基本クラスのコンストラクターから仮想メソッドを起動しています。つまり、UseBForSomethingElse (非仮想) は DoStuffImpl() (X で定義された仮想、純粋な @ A) から起動され、X基本構成を終了します (実際には、呼び出しを行ったときに X の基本構成にいます)。 . X の vtable はそのコンストラクターが実際に入力されるまで修正されないため、これにより「呼び出された純粋仮想関数」がトリガーされます。

これ私のマシンでも発生します。

于 2012-11-09T17:06:42.633 に答える