2012-01-27 17 views
7

OK, więc wybieram tutaj zmodyfikowaną trasę CRTP, aby uniknąć wyszukiwania funkcji wirtualnych. Ale ja po prostu nie mogę zrozumieć jednego błędu daje mi ...Dostęp do chronionych elementów z funkcji szablonu (statycznego) członka

więc staram się tłumaczyć:

class A 
{ 
public: 
    static void foo(A *pA) 
    { 
     pA->bar(); 
    } 

protected: 
    virtual void bar() 
    { 
     TRACE0(_T("A::bar\n")); 
    } 
}; 

class B : public A 
{ 
protected: 
    virtual void bar() 
    { 
     TRACE0(_T("B::bar\n")); 
    } 
}; 

który działa zgodnie z oczekiwaniami do:

class A 
{ 
public: 
    template <class T> 
    static void foo(T *pT) 
    { 
     pT->bar(); 
    } 

protected: 
    void bar() 
    { 
     TRACE0(_T("A::bar\n")); 
    } 
}; 

class B : public A 
{ 
protected: 
    void bar() 
    { 
     TRACE0(_T("B::bar\n")); 
    } 
}; 

który daje błąd:

error C2248: 'B::bar' : cannot access protected member declared in class 'B' 
see declaration of 'B::bar' 
see declaration of 'B' 
see reference to function template instantiation 'void A::foo<B>(T *)' 
being compiled with 
[ 
    T=B 
] 

teraz wiem, to jest łatwo ustalony przez dodanie friend class A; do klasy B, ale to nie jest bardzo schludny. Czy nie ma innej drogi?

Edycja: Przykład użycia:

B b; 
b.foo<B>(&b); 

edycji # 2: Funkcja element foo są statyczne, nie ma znaczenia, że ​​zauważone.

+0

Myślę, że tak się dzieje, ponieważ zajęcia dla rodziców nie mają specjalnego dostępu do chronionych członków potomnych (prawda?). Działa tylko dla dzieci, aby mieć dostęp do rodziców. –

+1

Jak powiedział Zan, klasa nadrzędna nie może uzyskać dostępu do chronionych członków klasy pochodnej (chyba że jest to oczywiście przyjaciel) –

+0

Brzmi o słuszności ... 'A :: foo' próbuje wywołać' B :: bar' i nie, ponieważ jest chroniony. 'friend class A' brzmi jak właściwe rozwiązanie. –

Odpowiedz

2

W pierwszym przypadku bar jest funkcją wirtualną i foo dostęp go przez wskaźnik do A sposób wywoływania wskaźnik funkcji i określony współczynnik vtable jak layout'ed według klasy A. Tak więc działa.

Jednak w drugim przypadku A::foo jawnie wywołuje funkcję inną niż wirtualna z innej klasy, do której nie ma dostępu. B::bar nie jest wirtualnym przeciążeniem A::bar - jest to zupełnie inna, niezwiązana funkcja.

Z tego powodu, sprawiając, że friend class A; jest najładniejszą, jaką można uzyskać, obawiam się.

Powiązane problemy