Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Спецификатор protected, ошибки при компиляции 
:(
    Опции темы
Alexey91
  Дата 4.10.2010, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Компилятор начинает выдавать ошибки, если я в базовом классе, использую protected и он выдает следующее:
 In member function `virtual Tlist* Tque::addlist(Tlist*)':
13: error: `Tlist*Tlist::next' is protected
288: error: within this context
13: error: `Tlist*Tlist::next' is protected
289: error: within this context
 In member function `virtual Tlist* Tque::del_(Tlist*)':
13: error: `Tlist*Tlist::next' is protected
300: error: within this context
 In member function `virtual Tlist* Tst::addlist(Tlist*)':
12: error: `int Tlist::data' is protected
321: error: within this context
13: error: `Tlist*Tlist::next' is protected
323: error: within this context


Я читаю, что спецификатор protected дает возможность использовать поля данных методам базового класса и всех его производных.
Но в производном класс Tque, его методы при обращении к данным из базового класса не могут получить доступ, и компилятор выдает ошибки, которые я написал выше.
Не понимаю почеемму..

Программа будет работать если спецификатор protected заменить на public

Код

#include <cstdio>
#include <cstdlib>
#include <iostream>

#define br putchar('\n');

using namespace std;

class Tlist
{
  protected:
   int data, L;         
   Tlist *next,*tail,*head;

  public:
         
   virtual Tlist* createlist(int);   
   virtual Tlist* search(Tlist*, int,int);
   virtual Tlist* movelist(Tlist *);
   virtual Tlist* addlist(Tlist *); 
   virtual Tlist* del_(Tlist *);                       
   virtual void printlist(Tlist *);
   virtual int add_data(int d);  
 
};      

int Tlist :: add_data(int d) {data=d; return data;}

void Tlist :: printlist (Tlist *head)
{
 Tlist *p;    
     
 p=head;
 while (p != NULL)
 {
  cout << (p->data) << " ";
  p=p->next;
 }
            // addresses
 
 br;
 
};     

Tlist* Tlist :: createlist (int num)
{  
 int i; 
 Tlist *p,*pred;
      
 L=num;     
       
 if (num > 0) 
 {
  p=head=pred=new Tlist;
  p->data=rand()%100;
  p->next=NULL;
 }           
 
 if (num > 1)            // check else if
 {
  for(i=0; i < num-1; i++)
  {
   p=new Tlist;
   p->data=rand()%100;
   pred->next=p;
   pred=p;
   tail=p;
  }
 } 
 
 p->next=NULL;
 
 printlist(head); 
 
 return head;             
};


Tlist* Tlist :: search (Tlist *head, int i,int k)
{
 Tlist *p;
 
 p=head;
 
 while (i != k)
 {
  i++;
  p=p->next;
 }
 
 return p;
};           

       

Tlist* Tlist :: addlist (Tlist *head)
{
 int i;     
 Tlist *pred,*res;
      
 cout << "Enter the number of item, followed by add record: ";
 cin >> i;
 
 pred=search(head,1,i);
 
 res=new Tlist;
 
 cout << "Enter data of new elem: ";
 cin >> res -> data;
 
 res -> next = pred -> next;
 pred -> next = res;
 
 L++;
 
 printlist(head);
 
 return head;
 
};

Tlist* Tlist :: del_ (Tlist *head)
{
 int i;
 Tlist *p,*pred,*res;     
      
 cout << "Enter the number of item, which you want to delete: ";
 cin >> i;      
 
 if ( i == 1)
 {
  p=head;
  head=p->next;
  delete p;
  L--;
 }  

 else if ( i == L )
 {  
  pred=search(head,1,L-1);
  tail=pred;  
  delete (*pred).next;
  tail->next=NULL; // MESTO C NULLEM
  L--;
 }
 
 else
 {
  pred=search(head,1,i-1);
  res=pred->next;
  pred->next=pred->next->next;
  delete res;
  L--;       
 }

 printlist(head);

 return head;


Tlist* Tlist :: movelist (Tlist *head)
{
 int a, b,c;
 Tlist *m,*pos,*tmp,*t;
 
 
 
 cout << "Movening elem, pos elem: ";
 cin >> a >> b;
 

 
 switch(a)
 {
  case 0: break;        
          
  case 1:
   if (b == 0) break;
   if (a == b) break;
   if ( b-a == 1) 
   {
    m=search(head,1,a);
    pos=search(head,1,b);
    c=m->data; m -> data= pos->data; pos->data=c;
   }                
   if (b == L)
   {
    puts("a");             
    m=search(head,1,a);
    pos=search(head,1,b);
    m=head->next;
    pos->next=head;
    head->next=NULL;
    head=m;
   } 
  
   break;
   
  default:
   if (b == a) break;
   if ( b-a==1) 
   {
    m=search(head,1,a);
    pos=search(head,1,b);
    c=m->data; m -> data= pos->data; pos->data=c;
    break;
   }    
   
   if (b == 0)
   {     
    if (a == L)
    {     
     m=search(head,1,a);
     t=search(head,1,a-1);
     t->next=NULL;
     m->next=head;
     return m;
    } 
    else if (a == 0) break;
    else
    {
     tmp=new Tlist;   
     m=search(head,1,a);
     tmp->data=m->data;
     t=search(head,1,a-1);
     t->next=t->next->next;
     delete m;
     tmp->next=head;
     return tmp; 
    }    
   }     
    m=search(head,1,a);
    pos=search(head,1,b);
    t=search(head,1,a-1);
    
    t->next=m->next;
    m->next=pos->next;
    pos->next=m;            

       
   break;      
}

 printlist(head);  
return head; 

}   

class Tque: public Tlist
{

      
  public:
                
   virtual Tlist* addlist(Tlist *); 
   virtual Tlist* del_(Tlist *);      
};

Tlist* Tque :: addlist(Tlist *head)
{
 int d,e;      
       
 Tlist *res,*p; 
 res=new Tlist;
    
 cout << "Enter the data of elem, movened in begin of que: ";
 cin >> d;
 res->add_data(d);
 
 tail=search(head,1,L);
 tail->next=res;
 res->next=NULL;
 
 printlist(head); 
 return head; 
}

Tlist* Tque :: del_(Tlist *head)
{
 Tlist *res;      
       
 res=head;
 head=head->next;
 delete res;     
  
 printlist(head); 
 
 return head;      
};       
                                  // stack   
class Tst: public Tque
{
 public:     
  virtual Tlist* addlist(Tlist *); 
};                   

Tlist* Tst :: addlist(Tlist *head)
{
 int d;      
 Tlist *res;
 res=new Tlist;
   
 cout << "Enter the data of elem, movened in begin of Stack: ";
 cin >> res->data;
 
 res->next=head;
 
 printlist(res);
 
 return res;
}  
        
int main()
{
 srand( time(NULL));   
    
 Tlist A,*q,*base;
 
 Tque B;
 
 Tst C;
 
 base=&A; 
  
 q=base->createlist(23);
 base->del_(q);
 
 q=C.addlist(q);
 C.del_(q);
 
 
 
 
 
 
 system("PAUSE");
 return 0;
}    



Всех спрашиваю, никто не может понять в чем дело..


Это сообщение отредактировал(а) Alexey91 - 4.10.2010, 11:20
PM   Вверх
bsa
Дата 4.10.2010, 11:19 (ссылка) |  (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



я так понимаю, ты делаешь односвязный список. правильно? Так вот, объект список содержит только два указателя - на первый элемент списка и на последний. А вот элемент списка содержит данные, указатель на следующий элемент и предыдущий (только двусвязный). Все это должно быть приватным. Наружу должны торчать только методы. А ты все запихал в один класс.
Более того, список просто не может быть базовым классом. Зачем? Список он и есть список.

protected означает, что доступ к полям объекта запрещен из вне этого объекта. т.е. this->next можно, а t->next нельзя.

PM   Вверх
Alexey91
Дата 4.10.2010, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Это вообще программа из лабораторной. 
Нужно было реализовать классы для списка, очереди, и стека, вот поэтому я список и через класс и делаю..
Но я так и не понял, в чем здесь ошибка?

А описание protected я из лекций взял..

Цитата

protected означает, что доступ к полям объекта запрещен из вне этого объекта. т.е. this->next можно, а t->next нельзя.


Под объектом вы понимаете, например Tlist B
или class Tlist ?

А то, что методы производных классов имеют доступ к данным базового класса это неверно?

Цитата

При объявлении какого-то члена класса с помощью спецификатора protected, он становится закрытым для всех классов, кроме производных.


Это сообщение отредактировал(а) Alexey91 - 4.10.2010, 11:36
PM   Вверх
bsa
Дата 4.10.2010, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



имеют. но они имеют только по указателю this.
Код
class X {
protected:
   int x;
};

class Y : public X {
public:
   int a() { x = 0; }  //ок
   int b(X &t) { t.x = 0; } //ошибка!!!
};


Цитата(Alexey91 @  4.10.2010,  12:31 Найти цитируемый пост)
Под объектом вы понимаете, например Tlist B
или class Tlist ?

это не объекты. это классы. А объекты, это такие переменные.

Обычно, protected используется для защиты виртуальных методов от доступа снаружи. Т.е. ты в базовом классе делаешь ряд виртуальных методов (в т.ч. и чисто виртуальных), которые наследники переопределяют. "Пользовательский" код не имеет прямого доступа к этим методам. Более того, он ему и не нужен (если все грамотно спроектировано).
Свойства класса вообще помещать нужно в приватную область, чтобы никто, кроме этого класса, доступа туда не имел. В этом случае ты обезопасишь себя от кучи проблем, которые могут возникнуть при изменении набора свойств. Например, ты написал односвязный список и десять наследников, которые напрямую меняют поля next, head, tail... А потом тебе понадобилось сделать его двусвязным... И тебе придется менять это не только в нем, но еще и в 10 наследниках. А если грамотно писать, то менять придется только в нем самом, так как наследники используют только методы.

Это сообщение отредактировал(а) bsa - 4.10.2010, 11:41
PM   Вверх
Alexey91
Дата 4.10.2010, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



так.. я правильно понимаю
что в функции a(), мы используем x производного класса?
а в функции b мы пытаемся обратиться к х из базового класса, но к полю х мы обратиться из производного класса не можем, потому что находимся вне объекта типа class X?

Указатель this присваивается неявно методу, в нем содержится адрес вызываемого объекта.

Это сообщение отредактировал(а) Alexey91 - 4.10.2010, 12:01
PM   Вверх
mes
Дата 4.10.2010, 12:12 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(bsa @  4.10.2010,  10:19 Найти цитируемый пост)
protected означает, что доступ к полям объекта запрещен из вне этого объекта. т.е. this->next можно, а t->next нельзя.

ммм.. "защита" устанавливается для классов, а не для объектов.. 



--------------------
PM MAIL WWW   Вверх
Alexey91
Дата 4.10.2010, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Может кто-нибудь дать четкое определение protected со всеми нюансами, а то я совсем запутался  smile 
PM   Вверх
mes
Дата 4.10.2010, 12:29 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alexey91 @  4.10.2010,  11:16 Найти цитируемый пост)
Может кто-нибудь дать четкое определение protected со всеми нюансами, а то я совсем запутался  


Цитата

— private; that is, its name can be used only by members and friends of the class in which it is
declared.
— protected; that is, its name can be used only by members and friends of the class in which it is
declared, and by members and friends of classes derived from this class (see 11.5).
— public; that is, its name can be used anywhere without access restriction.


Добавлено @ 12:33
Цитата(Alexey91 @  4.10.2010,  11:16 Найти цитируемый пост)
то я совсем запутался

вот пример, чтоб легче было разобраться 
Код

struct A { protected: int i; };

struct B : public A {
 void f () {
       A a; a.i++; //  нельзя.. доступ через класс А
       B b; b.i++; // можно.. доступ через класс B наследника А. 
 }
}


Добавлено @ 12:35
Цитата(Alexey91 @  4.10.2010,  09:58 Найти цитируемый пост)
Tlist* Tque :: addlist(Tlist *head)
{
 int d,e;      
       
 Tlist *res,*p; // доступ будет через Tlist , a значит протектед члены недоступны.. 



Модератор: добавил наследование от A

Это сообщение отредактировал(а) bsa - 4.10.2010, 12:40


--------------------
PM MAIL WWW   Вверх
Alexey91
Дата 4.10.2010, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



угу, пока буду думать!!
PM   Вверх
Alexey91
Дата 4.10.2010, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Цитата

struct A { protected: int i; };
struct B : public A {
 void f () {
       A a; a.i++; //  нельзя.. доступ через класс А
       B b; b.i++; // можно.. доступ через класс B наследника А. 
 }
}


Мы здесь обращаемся к унаследованному полю i в классе B.

А как обращаться из класса B к элементу i из класса А?

bsa говорил, что мы можем обращаться из производного класса в базовый класс, но по указателю this.
Или я его неправильно понял.

Обычно обращался так:
   имя_объекта.имя_класса::имя_компонента    .
   имя_объекта.имя_элемента   


Это сообщение отредактировал(а) Alexey91 - 4.10.2010, 13:05
PM   Вверх
mes
Дата 4.10.2010, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alexey91 @  4.10.2010,  12:03 Найти цитируемый пост)
Мы здесь обращаемся к унаследованному полю i в классе B.

А как обращаться из класса B к элементу i из класса А?

если он protected, то никак (исключение для друзей)
можно только к унаследованным протектед членам.. 

Цитата(Alexey91 @  4.10.2010,  12:03 Найти цитируемый пост)
но по указателю this.

объект роли не играет, важен его тип.. 
Код

void B::f() 
{  ++ i;                       // можно
   static_cast<А*>(this)->i++; // нельзя, так как "this" теперь класса A;
}




Цитата(Alexey91 @  4.10.2010,  12:03 Найти цитируемый пост)
Обычно обращался так:

Цитата

B.b; b.A::i++; // доступ все равно через класс B, не смотря на специализацию... 



Это сообщение отредактировал(а) mes - 4.10.2010, 13:35


--------------------
PM MAIL WWW   Вверх
Alexey91
Дата 4.10.2010, 13:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Цитата

можно только к унаследованным протектед членам.. 


т.е. мы можем обращаться только к более низшим по иерархии классам?
Из класса А мы можем обратиться к protected полям из класса B?
Не ясно как это можно сделать..

Код



#include <cstdio>
#include <cstdlib>
#include <iostream>

struct A {
        protected: int i;
 public:
        
 void f()
 {
      i=0;
        i++; 
        printf("%d",i);
      }
 };

struct B : public A {
 void f () {
      
      i=0;
        i++;
        printf("%d",i);

 }
};

int main()
{
    B b;
    A a;
    
    b.f();
    a.f();
 
 system("PAUSE");
 return 0;
}    



Исправьте пожалуйста, я mes не те звездочки (ОТРИЦАТЕЛЬНЫЕ) поставил (((

Это сообщение отредактировал(а) Alexey91 - 4.10.2010, 14:16
PM   Вверх
mes
Дата 4.10.2010, 14:03 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alexey91 @  4.10.2010,  12:53 Найти цитируемый пост)
т.е. мы можем обращаться только к более низшим по иерархии классам?
Из класса А мы можем обратиться к protected полям из класса B?
Не ясно как это можно сделать..


не понял суть вопроса.. 




--------------------
PM MAIL WWW   Вверх
Alexey91
Дата 4.10.2010, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 18.9.2008

Репутация: нет
Всего: нет



Цитата(mes @  4.10.2010,  13:31 Найти цитируемый пост)
Цитата(Alexey91 @  4.10.2010,  12:03 Найти цитируемый пост)
Мы здесь обращаемся к унаследованному полю i в классе B.

А как обращаться из класса B к элементу i из класса А?

если он protected, то никак (исключение для друзей)
можно только к унаследованным протектед членам.. 


Как можно обратиться к унаследованным протектед членам (или под членом вы понимаете функцию-член)?
PM   Вверх
bsa
Дата 4.10.2010, 14:16 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



к унаследованным ты можешь обратиться напрямую. Но доступа к неунаследованным у тебя нет. Т.е. если ты из класса B (наследника A) пытаешься изменить защищенное свойство объекта, класса A, то получишь от компилятора по рукам. А если пытаешься изменить тоже самое свойство, но от объекта класса B, то все будет в порядке.
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1064 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.