3

このコードが機能しないことはわかっており、その理由もわかっていますが、代替手段はありますか?

class A
{
public:
    A(void){}
    virtual ~A(void){}
protected:
    A* parent;
    int a;
};

class B : public virtual A
{
public:
    B(void){}
    virtual ~B(void){}
protected:
    void f(){ ((B*)parent)->a; }
};

は仮想基底クラスであるため、にキャストparentすることはできません。キャストしないとエラーになります。すべてのメンバーを公開する必要がないことを願っています。A::a にアクセスする方法を知っている人はいますか?B*Aparent

編集

から派生したクラスBは にアクセスできないため、フレンドの使用は機能しませんA::a

4

7 に答える 7

2

いくつかのオプション:

  1. 公開aする
  2. a-のパブリック セッター/ゲッター メソッドを作成します。
  3. B をクラス A のフレンドにする(または単に関数f())

A (または特定の関数) のみが のメンバーにアクセスできるようにする場合は、3 番目のオプションが他の 2 よりもうまく機能しますA。一方、他の 2 つのオプションを使用すると、そのメンバーのみを公開できます (ただし、全員に公開されます)。

于 2013-04-12T13:35:18.250 に答える
1

上記のコメントから回答を作成しました。これは、テストして問題なくコンパイルできるためです。

キャストがないと、B の A の保護されたフィールドにアクセスしようとしているため、おそらく失敗します。パブリック ゲッターを追加して、B* へのキャストを削除するだけです。

class A
{
public:
    A(void){}
    virtual ~A(void){}
    int getA() { return a; }
protected:
    A* parent;
    int a;
};

class B : public virtual A
{
public:
    B(void){}
    virtual ~B(void){}
protected:
    void f(){ (parent)->getA(); }
};
于 2013-04-12T13:26:07.887 に答える
1

これは機能します:

class A {
public:
    A(void){}
    virtual ~A(void){}
protected:
    A* parent;
    int a;
    int parent_a(){ return parent->a;}
};

class B : public virtual A
{
public:
    B(void){}
    virtual ~B(void){}
protected:
    void f(){ A::parent_a(); }
};

ご了承ください:

  • a外の世界にさらされることなく、
  • から実質的に継承するため、取得aしたものは正しいものである必要があります。そのため、フィールドを取得する前にtoの動的キャストが成功すると、上記のソリューションと同じものを返す必要があります。BAparentBa

では、なぜこれが機能するのでしょうか。

クラスは暗黙的にそれ自体の友達だからです。

于 2013-04-12T13:55:24.830 に答える
1

それdynamic_castがそのためです。コードを再設計したくない場合は、C スタイルのキャストをdynamic_cast:

void f() { dynamic_cast<B*>(parent)->a; }

これが正しくA機能するためには、少なくとも 1 つの仮想関数が必要です (この関数のように)。さらに、parentが実際には type のオブジェクトを指していない場合、キャストは null ポインターを生成しますB

于 2013-04-12T14:48:48.287 に答える
0

みんなありがとう、友達を使ったり、変数ごとに追加の関数を作成したりするなど、いくつかの使用可能な可能性が言及されました。これはいくつかのシナリオで機能する可能性がありますが、私の場合は機能しません。各派生クラスをフレンドとして追加すると、クラスを追加したいときにライブラリが使いにくくなるという問題があります。変数ごとに関数を追加すると、クラスによっては 100 を超える関数が追加されることになります。

私が最終的な解決策として行ったのは、キャストではなくコピーを作成することでした。実行速度は少し遅くなりますが、コードはきれいなままです。速度の問題に対抗するため。ローカル変数へのアクセスは、グローバル変数へのアクセスよりもはるかに高速です。

これが今の様子です:

class A
{
public:
    A* parent;
    virtual ~A(void){}
    virtual A & operator = (const A & x)
    {
        a = x.a;
        parent = x.parent;
        return *this;
    }
protected:
    int a;
};

class B : public virtual A
{
public:
    B(void){}
    virtual ~B(void){}
    using A::operator =;
    virtual B & operator = (const B & x)
    {
        A::operator = (x);
        return *this;
    }
    void f(void)
    {
        B p;
        p = *parent;
        int x = p.a;//Allowed.
    }
};

より良い解決策がある場合は、お気軽に投稿してください。

于 2013-04-13T16:44:01.323 に答える
0
class B : public virtual A
{
public:
    B(void){}
    virtual ~B(void){}
protected:
    void f(){ this->a; }
};

親クラス(Bのマザークラス)から保護されたメンバーにアクセスできます。

于 2013-04-12T13:22:10.647 に答える