web-dev-qa-db-fra.com

Classe de base inaccessible malgré l'amitié

Il y a des tonnes de questions concernant cette erreur et toutes les réponses semblent impliquer que le downcasting est impossible. Seulement cette réponse mentionne l'amitié comme solution possible, du moins si je comprends bien. Cependant, le code suivant (éléments non pertinents supprimés pour plus de clarté) ne se compile pas:

class C;

class A {
    friend class C;  // this does not help
};

class B : protected A {
    friend class C;  // this does not help either
};

class C {
    public:
    void foo(A* a) {};
};

B b;
C c;

void bar()
{
    c.foo(&b);  // this produces error: class A is an inaccessible base of B
}

Pourquoi l'amitié ne fonctionne pas sur une référence? Après tout, "C" est parfaitement capable d'appeler des méthodes protégées de "A" via un pointeur vers "B".

L'erreur complète est

prog.cc: In function 'void bar()':
prog.cc:20:13: error: 'A' is an inaccessible base of 'B'
   20 |     c.foo(&b);
11
Maple

Dans la portée globale, B n'est pas visible comme A, en raison de l'héritage protégé.

Seule la classe B elle-même, les classes héritées de B et la classe C (parce que la relation d'amitié) "savent" que B hérite de A. Mais le reste du monde (y compris la portée mondiale) ne le fait pas '.

Donc, pour réaliser ce que vous voulez, vous pouvez appeler

c.foo(&b)

dans la portée C, par exemple en utilisant une fonction wrapper, quelque chose comme (bien que mauvaise décision de conception):

#include <iostream>
#include <cstdlib>

class C;


class A {
    friend class C;  // this does not help
};

class B : protected A {
    friend class C;  // this does not help either
};

class C {
public:
    void foo() {
        B b;
        foo(&b);  // this call is OK within C-scope
    }
private:
    void foo(A* /*a*/) {
        std::cout << "C::foo(A* a)\n";
    };
};


int main()
{
    std::cout << "Hello, Wandbox!" << std::endl;
    B b;
    C c;
    //c.foo(&b);  // this produces error: class A is an inaccessible base of B
    c.foo();      // this is calling c.foo(A*) internally
}

ou en direct :

1
StPiere