Static-члены (данные) класса
Компоненты-данные могут быть объявлены с модификатором класса памяти static. Класс, содержащий static компоненты-данные, объявляется как глобальный (локальные классы не могут иметь статических членов). Static-компонента совместно используется всеми объектами этого класса и хранится в одном месте. Статическая компонента глобального класса должна быть явно определена в контексте файла. Использование статических компонент-данных класса продемонстрируем на примере программы, выполняющей поиск введенного символа в строке. #include "string.h" #include "iostream.h" enum boolean {fls,tru}; Class cls { char *s; public: static int k; // объявление static-члена в объявлении класса static boolean ind; void inpt(char *,char); void print(char); }; int cls::k=0; // явное определение static-члена в контексте файла boolean cls::ind; void cls::inpt(char *ss,char c) { int kl; // длина строки cin >> kl; ss=new char[kl]; // выделение блока памяти под строку cout << "введите строку\n"; cin >> ss; for (int i=0; *(ss+i);i++) if(*(ss+i)==c) k++; // подсчет числа встреч буквы в строке if (k) ind=tru; // ind==tru - признак того, что буква есть в строке delete [] ss; // освобождение указателя на строку } void cls::print(char c) { cout << "\n число встреч символа "<< c <<"в строках = " << k; } void main() { cls c1,c2; char c; char *s; cls::ind=fls; cout << "введите символ для поиска в строках"; cin >> c; c1.inpt(s,c); c2.inpt(s,c); if(cls::ind) c1.print(c); else cout << "\n символ не найден"; } Объявление статических компонент-данных задает их имена и тип, но не инициализирует значениями. Присваивание им некоторых значений выполняется в программе (вне объекта). В функции main() использована возможная форма обращения к static-компоненте cls::ind (имя класса:: идентификатор), которая обеспечивается тем, что идентификатор имеет видимость public. Это дальнейшее использование оператора разрешения контекста “::”.
Отметим основные правила использования статических компонент: - статические компоненты будут одними для всех объектов данного класса. То есть ими используется одна область памяти; - статические компоненты не являются частью объектов класса; - объявление статических компонент-данных в классе не является их описанием. Они должны быть явно описаны в контексте файла; - локальный класс не может иметь статических компонент; - к статической компоненте st класса cls можно обращаться cls::st, независимо от объектов этого класса, а также используя операторы. и -> при использовании объектов этого класса; - статическая компонента существует даже при отсутствии объектов этого класса; - статические компоненты можно инициализировать, как и другие глобальные объекты, только в файле, в котором они объявлены.
Указатель this Как отмечалось выше, если некоторая функция является компонентой объекта, то при вызове этой функции к компонентам-данным этого объекта можно обращаться по имени (опуская имя объекта). Например, пусть имеется объявление двух объектов: my_class ob1,ob2; Вызовы компонент-функций имеют вид: ob1.fun_1(); ob2.fun_2(); Пусть в обеих функциях содержится инструкция: cout << str; При объявлении двух объектов создаются две компоненты-данные str. Возникает вопрос, откуда каждая из двух функций узнает, с какой из компонент ей работать (точнее, где она расположена). Ответ состоит в следующем. В памяти для каждого располагаемого объекта создается скрытый указатель, адресующий начало выделенной под объект области памяти. Получить значение этого указателя в компонентах-функциях можно посредством ключевого слова this. Для любой функции, принадлежащей классу my_class, указатель this неявно объявлен так: my_class *const this; Таким образом, при объявлении объектов ob1 и ob2 создаются два this- указателя на эти объекты. Следовательно, любая функция, являющаяся компонентой некоторого объекта, при вызове получает this-указатель на этот объект. И приведенная выше инструкция в функции воспринимается как
cout << this->str; Однако эта форма записи избыточна. С другой стороны, явное использование указателя this эффективно при решении некоторых задач. Рассмотрим пример использования this-указателя на примере упорядочивания чисел в массиве. #include<stdio.h> #include<iostream.h> Class m_cl { int a[3]; public: m_cl srt(); // функция упорядочивания информации в массиве m_cl *inpt(); // функция ввода чисел в массив void out(); // вывод информации о результате сортировки }; m_cl m_cl::srt() // функция сортировки { for(int i=0;i<2;i++) for(int j=i;j<3;j++) if (a[i]>a[j]) {a[i]=a[i]+a[j]; a[j]=a[i]-a[j]; a[i]=a[i]-a[j];} return *this; // возврат содержимого объекта, на который } // указывает указатель this m_cl * m_cl::inpt() // функция ввода { for(int i=0;i<3;i++) cin >> a[i]; return this; // возврат скрытого указателя this } // (адреса начала объекта) void m_cl::out() { cout << '\n'; for(int i=0;i<3;i++) cout << a[i] << ' '; } main() { m_cl o1,o2; // описание двух объектов класса m_cl o1.inpt()->srt().out(); // вызов компонент-функций первого объекта o2.inpt()->srt().out(); // вызов компонент-функций второго объекта return 1; } Вызов компонент-функций для каждого из созданных объектов осуществляется: o1.inpt()->srt().out; Приведенная инструкция интерпретируется следующим образом: сначала вызывается функция inpt для ввода информации в массив данных объекта о1; функция inpt возвращает адрес памяти, где расположен объект о1; далее вызывается функция сортировки информации в массиве, возвращающая содержимое объекта о1; после этого вызывается функция вывода информации. Ниже приведен текст еще одной программы, использующей указатель this. В ней выполняется добавление строки-компоненты одного объекта к строке-компоненте другого. #include<iostream.h> #include<string.h> class B; // предварительное объявление класса В Class A { char *s; public: A(char *s) // конструктор с параметром char* { this->s=new char[strlen(s)+1]; // память под строку-компоненту strcpy(this->s,s);// копирование строки-аргумента в строку-компоненту } ~A(){delete [] this->s;} void pos_str(char *); }; Class B { char *ss; public: B(char *ss) // конструктор с параметром char* { this->ss=new char[strlen(ss)+1]; // память под строку-компоненту
strcpy(this->ss,ss); // копирование строки-аргумента в } // строку-компоненту ~B(){delete [] this->ss;} char *f_this(void){return this->ss;} }; void A::pos_str(char *s) { char *dd; int i,ii; dd=new char[strlen(this->s)+strlen(s)+2]; //память для перезаписи 2 строк strcpy(dd,this->s); // перезапись в dd строки объекта a1 dd[strlen(this->s)]=' '; // удаление ’\0’ ii=strlen(this->s); for(i=0;*(s+i);i++) // дозапись в dd строки объекта b1 *(dd+ii+i+1)=*(s+i); *(dd+ii+i+1)=0; delete [] this->s; // удаление строки объекта a1 this->s=dd; // перенаправление указателя на строку dd cout << this->s << endl; } void main(void) { A a1("aa bcc dd ee"); B b1("bd"); a1.pos_str(b1.f_this()); } В результате выполнения программы получим: aa bcc dd ee bd Отметим основные правила использования this-указателей: - каждому объявляемому объекту соответствует свой скрытый this- указатель; - this-указатель может быть использован только для нестатической функции; - this указывает на начало своего объекта в памяти; - this не надо дополнительно объявлять; - this передается как скрытый аргумент во все нестатические (не имеющие спецификатора static) компоненты-функции своего объекта; - указатель this - локальная переменная и недоступна за пределами объекта; - обращаться к скрытому указателю можно this или *this.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|