2013-05-09 17 views
6

Heres il mio codice:Impossibile accedere membro protetto della classe base dalla classe derivata

#include <iostream> 
#include <cmath> 
#include <sstream> 
using namespace std; 

class root 
{ 
    protected : 

      int size; 
      double *array; 

    public : 

     virtual ~root() {} 
     virtual root* add(const root&) = 0; 
     virtual root* sub(const root&) = 0; 
     virtual istream& in(istream&, root&) = 0; 
     virtual int getSize() const = 0; 
     virtual void setSize(int); 
}; 

class aa: public root 
{ 

    public : 

     aa(); 
     aa(int); 
     aa(const aa&); 
     root* add(const root& a); 
     root* sub(const root& a); 
     istream& in(istream&, root&){} 
     int getSize() const; 
     void setSize(int); 
}; 

class bb: public root 
{ 
public: 
    bb() { } 
    bb(const bb& b) { } 
    root* add(const root& a); 
    root* sub(const root& a); 
    istream& in(istream&, root&){} 
    int getSize() const{} 
    void setSize(int){} 
}; 

aa::aa() 
{ 
    size = 0; 
    array = NULL; 
} 

aa::aa(int nsize) 
{ 
    size = nsize; 
    array = new double[size+1]; 
    for(int i=0; i<size; i++) 
     array[i] = 0; 
} 

root* aa::add(const root& a) 
{ 
    for (int i=0; i<a.size; i++) 
     array[i] += a.array[i]; 
    return *this; 
} 

root* aa::sub(const root& a) 
{ 
} 

int aa::getSize() const 
{ 
    return size; 
} 

void aa::setSize(int nsize) 
{ 
    size = nsize; 
    array = new double[size+1]; 
    for(int i=0; i<size; i++) 
     array[i] = 0; 
} 

root* bb::add(const root& a) 
{ 
    return new bb(); 
} 

root* bb::sub(const root& a) 
{ 

} 

int main(int argc, char **argv) 
{ 
} 

Quando voglio accedere size o un array in classe derivata, ho appena cant perché il mio compilatore dice:

/home/brian/Desktop/Temp/Untitled2.cpp||In member function ‘virtual root* aa::add(const root&)’:| 
/home/brian/Desktop/Temp/Untitled2.cpp|10|error: ‘int root::size’ is protected| 
/home/brian/Desktop/Temp/Untitled2.cpp|66|error: within this context| 
/home/brian/Desktop/Temp/Untitled2.cpp|11|error: ‘double* root::array’ is protected| 
/home/brian/Desktop/Temp/Untitled2.cpp|67|error: within this context| 
/home/brian/Desktop/Temp/Untitled2.cpp|68|error: cannot convert ‘aa’ to ‘root*’ in return| 
||=== Build finished: 5 errors, 0 warnings ===| 

Ho letto che i membri protetti sono privati ​​nelle classi derivate, quindi sembra essere ok, ma non lo è. Come risolvere questo?

risposta

6

Ho letto che i membri protetti sono privati ​​nelle classi derivate, quindi sembra essere ok, ma non lo è.

Non è perché un membro di dati protected ereditato da una classe base A (root, in questo caso) da una classe derivata B (aa, in questo caso) è accessibile purché sia ​​accessibile su un oggetto di tipo B (aa). Qui, si accede attraverso un oggetto di tipo A (root):

root* aa::add(const root& a) 
{ 
    for (int i=0; i<a.size; i++) 
    //    ^^^^^^ 
    //    Accessing size on an object of type `root`, not `aa`! 
     array[i] += a.array[i]; 
    return *this; 
} 

al comma 11.4/1 della C++ 11 standard:

un controllo di accesso ulteriore al di là di quelli descritti in precedenza nella Clausola 11 viene applicato quando un membro non statico dati membro o funzione membro non statico è un membro protetto della sua classe di denominazione (11.2). Come descritto in precedenza , l'accesso a un membro protetto è concesso perché il riferimento si verifica in un amico o membro di qualche classe C. Se l'accesso deve formare un puntatore al membro (5.3.1), lo specificatore nome-nidificato deve denotare C o una classe derivata da C. Tutti gli altri accessi implicano un'espressione dell'oggetto (possibilmente implicita) (5.2.5) . In questo caso, classe dell'espressione dell'oggetto è C o una classe derivata da C. [Esempio:

class B { 
protected: 
    int i; 
    static int j; 
}; 
class D1 : public B { 
}; 
class D2 : public B { 
    // ... 
    void mem(B*,D1*); 
}; 

void D2::mem(B* pb, D1* p1) { 
    pb->i = 1; // ill-formed 
    p1->i = 2; // ill-formed 
    // ... 
    i = 3; // OK (access through this) 
    B::i = 4; // OK (access through this, qualification ignored) 
    j = 5; // OK (because j refers to static member) 
    B::j = 6; // OK (because B::j refers to static member) 
} 

- esempio fine]

Per risolvere questo problema, è necessario fornire setter/getter pubblici. Hai già una funzione di getSize(), così invece di scrivere questo:

for (int i=0; i<a.size; i++) 
//    ^^^^^^ 

si potrebbe scrivere questo:

for (int i=0; i<a.getSize(); i++) 
//    ^^^^^^^^^^^ 

Allo stesso modo, si dovrà fornire funzioni per ottenere/impostare il valore della n- esimo elemento di array, in modo che si potrebbe scrivere:

array[i] += a.get_at(i); 

si noti che l'espressione sul lato sinistro della += è OK, perché 012.321.003 È possibile accedere atramite this (vedere anche l'esempio precedente dello standard C++ 11).

+0

grazie :) Quindi, c'è un modo per "risolvere" questo? –

+2

@BrianBrown: si potrebbe avere una funzione getter 'public' chiamata' size() 'su' root', è accettabile? –

+0

L'ho già definito in 'root' ma è puramente virtuale (è sbagliato, giusto?). Ma che ne dici di un array? –