3

重複の可能性:
派生クラスの保護されたメンバーへのアクセス

抽象基本クラスと、それから派生した具体的なテンプレート クラスがあり、基本クラスへのポインターを使用するメソッドがある場合、派生クラスは自分自身を派生として認識しなくなったようです。

class AbstractBase
{
protected:
    virtual void test() = 0;
};

template < class T >
class Derived : public AbstractBase
{
public:
    virtual void call( AbstractBase* d ) { d->test(); }  //  Error!
protected:
    virtual void test() {}
};

int main()
{
    Derived< int > a;
    Derived< int > b;

    b.call( &a );

    return EXIT_SUCCESS;
}

このエラーは次のとおりです。

「virtual void AbstractBase::test()」は保護されています

protectedコンパイラが間違っているわけではありません。それは間違いありませDerived< T >AbstractBase

4

2 に答える 2

1

これはテンプレートとは関係ありませんが、保護されたメンバー アクセス全般に関係しています。公開されている最新のドラフト C++標準のセクション 11.4 保護されたメンバー アクセス [class.protected]を参照してください。

非静的データメンバーまたは非静的メンバー関数がその命名クラス (11.2) の保護されたメンバーである場合、条項 11 で前述したものを超える追加のアクセスチェックが適用されます。アクセスがメンバーへのポインターを形成する場合 (5.3.1)、nested-name-specifier は C または C から派生したクラスを示す必要があります。他のすべてのアクセスには、 (おそらく暗黙の) オブジェクト式 (5.2.5)。この場合、オブジェクト式のクラスは C または C から派生したクラスでなければなりません。

[例:

class B {
protected:
    int i;
    static int j;
};

class D1 : public B {
};

class D2 : public B {
    friend void fr(B*,D1*,D2*);
    void mem(B*,D1*);
};

void fr(B* pb, D1* p1, D2* p2) {
   pb->i = 1; // ill-formed
   p1->i = 2; // ill-formed
   p2->i = 3; // OK (access through a D2)
   p2->B::i = 4; // OK (access through a D2, even though
                 // naming class is B)
   int B::* pmi_B = &B::i; // ill-formed
   int B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*)
   B::j = 5; // OK (because refers to static member)
   D2::j = 6; // OK (because refers to static member)
}
于 2012-08-04T15:18:34.713 に答える