2013-05-09 2 views
6

Heres мой код:не удается получить доступ к защищенному члену в базовом классе из производного класса

#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) 
{ 
} 

Когда я хочу, чтобы получить доступ к size или array в производном классе, я просто не могу, потому что мой компилятор говорит:

/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 ===| 

Я читал, что защищенные члены являются частными в производных классах, поэтому кажется, что все в порядке, но это не так. Как это исправить?

ответ

6

Я читал, что защищенные члены являются частными в производных классах, поэтому кажется, что все в порядке, но это не так.

Это не потому, Чтоб написать protected данных, унаследованных от базового класса A (root, в данном случае) с помощью производного класса B (aa, в данном случае) доступен до тех пор, как доступ к нему осуществляется на объект типа B (aa). Здесь вы к нему доступ через объект типа 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; 
} 

в соответствии с пунктом 11.4/1 C++ 11 Стандарт на:

дополнительная проверка доступа, кроме описанных выше в пункте 11 применяется, когда нестатические данные или нестатическая функция-член являются защищенным членом его класса именования (11.2). Как описано выше, доступ к защищенному члену предоставляется, поскольку ссылка встречается у друга или члена некоторого класса C. Если доступ заключается в формировании указателя на член (5.3.1), спецификатор вложенных имен должен обозначать C или класс , полученный из C. . Все другие обращения включают (возможно неявное) выражение объекта (5.2.5) , В этом случае класс выражения объекта должен быть С или класс, производный от C. [Пример:

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) 
} 

- конец пример]

Чтобы это исправить, вам необходимо предоставить публичные сеттеры/геттеры. У вас уже есть getSize() функцию, поэтому вместо того, чтобы писать это:

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

Вы можете написать это:

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

Кроме того, вы должны будете предоставить функции для получения/установки значения n- й элемент array, так что вы могли бы написать:

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

Обратите внимание, что выражение на левой стороне += в порядке, потому что array осуществляется через this (см. Также пример выше из стандарта C++ 11).

+0

спасибо :) Итак, есть ли способ «исправить» это? –

+2

@BrianBrown: У вас может быть функция 'public' getter, называемая' size() 'на' root', это приемлемо? –

+0

Я определил его уже в 'root', но его чистый виртуальный (это неправильно, правда?). Но как насчет массива? –