- •Структура класса, как нового типа данных. Что входит в состав каждого из объявляемых объектов класса?
- •В состав любого объекта класса входят только данные-элементы этого класса, но не входят функции-элементы этого же класса.
- •10. Размещение объекта в глобальной области, в стеке или в динамической памяти.
- •19. Объявление и определение дружественной функции класса.
- •37. Явное и неявное использование указателя this в функциях класса. Организация сцепления вызовов функций класса.
- •46. На что распространяются действия конструктора и деструктора класса?
Вместо примеров програм можно написать их номер и на еомпьютере показать саму программу( т.к. все проги эти должны быть запущены и отлажены на компьютере)
То что написано крассным курсивом можно не переписывать( по вашему усмотрению) это пояснения для того что бы понять следующий текст.
Структура класса, как нового типа данных. Что входит в состав каждого из объявляемых объектов класса?
Всякий новый АТД создаётся на основе структуры данных, называемой классом, который имеет вид:
class имя класса { public: открытые функции и переменные класса private: закрытые функции и переменные класса }; |
Пример объявления класса newtype:
class newtype { public: newtype(int=0);//прототип конструктора класса с умолчанием void set_a(int);//объявления прототипов int get_a();//функции класса private: int a;//объявление переменной класса типа int }; |
Объявление любого класса начинается с ключевого слова class, за которым следует имя класса. Тело класса, заключённое в фигурные скобки, составляют члены класса – переменные встроенных типов и функции, созданные пользователем для их обработки.
Данные и функции класса подразделяются на открытые (public) и закрытые (private) члены класса.
Public – переменные и функции класса доступны как любой функции данного класса, так и любой другой функции программы, в зоне видимости которой находятся члены класса типа public. В свою очередь, private функции и элементы класса доступны только функциям-элементам данного класса типов public или private, но не доступны любой другой функции программы.
В теле класса спецификаторы доступности public и private заканчиваются (:) и могут встречаться произвольное число раз.
Спецификатор private можно опустить в начале описания класса, т.к. он устанавливается по умолчанию. После закрывающей фигурной скобки тела класса должна стоять (;).
В состав любого объекта класса входят только данные-элементы этого класса, но не входят функции-элементы этого же класса.
10. Размещение объекта в глобальной области, в стеке или в динамической памяти.
Oбъявление класса – это всего лишь описание схемы будущего использования памяти, т.е. при объявлении класса не выделяется память ни в области кода, ни в области глобальных переменных, ни в области стека, ни в динамической памяти.
Для привязки объявленного класса к памяти необходимо создать экземпляр класса в памяти, который называется объектом данного класса. Каждый класс может иметь сколь угодно много точек привязки к памяти как на внешнем, так и на внутреннем уровнях. Другими словами, каждому классу может соответствовать несколько объектов, которые будут отличаться друг от друга местом расположения в памяти.
В состав любого объекта класса входят только данные-элементы этого класса, но не входят функции-элементы этого же класса.
Если объекты класса определены на внешнем уровне, то они располагаются в области глобальных переменных.
В случае объявления объектов класса на внутреннем уровне, они располагаются в стеке или в динамической области памяти.
19. Объявление и определение дружественной функции класса.
Доступ к открытым данным-элементам класса типа public имеет любая функция не принадлежащая классу. При этом обращение к открытом данному-элементу класса в режимах записи/чтения осуществляется или по имени объекта, или по указателю на объект, или по ссылке на объект. Например:
ob.c = 25 или obPtr->c=25; или obRef->c=25;, |
где ob – имя объявленного объекта, а с – переменная типа public из ob.
Доступ к закрытым данным-элементам класса типа private имеет или функции класса, или дружественные функции данному классу.
Любая функция класса обладает собственным указателем this, через который она адресует любой объект класса, по отношению к которому вызвана. Именно принадлежность this в любой функции класса позволяет таким функциям обращаться к открытым и закрытым переменным любого объекта класса, используя только имена этих переменных без указания их принадлежности объекту, по отношению к которому вызвана функция.
Дружественные функции не являются элементами класса, т.е. не обладают указателем this, однако имеют возможность доступа как к открытым, так и закрытым данным-элементам класса.
Обращение к закрытым данным-элементам класса со стороны дружественной функции осуществляется также как и к открытым данным класса, т.е. по имени объекта или по указателю, или по ссылке на объект. При этом объект класса или объявляется локально в теле дружественной функции, или передается ей через параметр по значению или по указателю, или ссылке на адрес загрузки объекта.
Чтобы объявить функцию другом класса, необходимо перед ее прототипом в описании класса поставить ключевое слово friend. Объявление дружественности (friend) не имеет отношение к спецификаторам доступа public и private к элементам класса. поэтому объявление дружественной функции может быть выполнено в любом месте описания класса.
Следующий пример иллюстрирует применение дружественных функций.
//PROG.4.1.CPP – имя файла #include<iostream> using namespace std;//множество зарезервированных имен, отличных от стандартных занятых языком class myclass{ public: myclass(int i, int j){n=i; d=j;} private: int n,d; //Объявление дружественных функций, в которые объект класса передается через параметры по значению friend int div(myclass ob); } //Определение дружественной функции класса int div(myclass ob) { if(!(ob.n%ob.d)) reurn 1; else return 0; } int main() { setlocale(LC_ALL, “.1251”) myclass ob1(10,2), ob2(13,3); if(div(ob1)) cout << “10 без остатка делится на 2”<<endl; else cout << “10 без остатка не делится на 2”<<endl; if(div(ob2)) cout << “13 без остатка делится на 3”<<endl; else cout << “13 без остатка не делится на 3”<<endl; return 0; } |
//PROG.4.2.CPP – имя файла #include<iostream> using namespace std; class Count{ //Объявление дружественной функции, в которой через ссылочный параметр передается адрес загрузки объекта класса friend void setX(Count&, int); public: Count (){x=0;}//конструктор класса с умолчанием void print()const{cout<<x<<endl;} private: int x; } void setX(Count &c, int val) { c.x=val; } int main() { setlocale(LC_ALL, “.1251”) Count ob; cout << “ob.x после своего создания: ”; ob.print(); cout << “ob.x после вызова дружественной функции setX: ”; setX(ob, 8); ob.print(); return 0; } |
Из приведенных примеров следует, что при определении дружественных функций, во-первых, не указывается принадлежность классу, и во-вторых, не используется ключевое слово friend.
Основным аргументом в пользу существования дружественных функций, нарушающих принцип инкапсуляции ООП, является необходимость доступа со стороны одной функции к закрытым данным-элементам объектов различных классов.
28. Что является значением “указателя” и ”ссылки” на объект? Чем “ указатель” отличается от “ссылки” на объект?
Значением «указателя» является адрес начала загрузки в памяти объектов, а значением «ссылки» является адрес загрузки объектов в области стека оперативной памяти.
Ссылки на объекты являются ничем иным как указателями. Но при этом ссылки обладают следующими свойствами, которые отличают их от указателей:
1. Ссылки являются константными указателями, т.е. значение адресов, которые однажды занесены в ссылки, не могут быть изменены в течение программы. Следовательно, ссылки являются константными переменными.
2. Константность ссылок обуславливает обязательную инициализацию на этапе их объявления. В PROG1.CPP обязательная инициализация ссылок осуществляется оператором newtype& ob5Ref = ob5,&ob6Ref = ob6Ref;. Альтернативным способом объявления ссылок ob5Ref и ob6Ref является:
newtype &ob5Ref = ob5;
newtype &ob6Ref = ob6;.
Таким образом, из-за констанстности ссылок недопустимым является следующий оператор объявления ссылок:
newtype &ob5Ref, &ob6Ref;
3. Ссылки являются неявно разыменуемыми указателями, т.е. в ссылках, в отличие от указателей, не используется операция разыменования или разадресации (*), т.к. разыменование осуществляется автоматически.
Использование ссылок позволяет имитировать режим прямой адресации к объектам по аналогии с логическими адресами объектов ob5 и ob6. Например, в операторах
ob5.set_a(50);
ob6.set_a(60);
вызов функции set_a выполняется в режиме прямой адресации объектов ob5 и ob6 с использованием операции доступа (.). Аналогичными по внешнему виду являются операторы
ob5Ref.set_a(50);
ob6Ref.set_a(60);,
которые осуществляют вызов функции set_a как бы в режиме прямой адресации, но не объектов, а ссылок ob5Ref и ob6Ref на эти объекты, хотя на самом деле имеет место косвенная адресация объектов. Эффект псевдопрямой адресации определяет толкование ссылки, например ob5Ref, как логического синонима исходного имени объекта ob5.
Как и прежде конструктор с умолчанием автоматически вызывается после объявления каждого из объектов ob5 и ob6, но при этом после имени каждого объекта в круглых скобках указано значение, которое в качестве аргумента передается конструктору для инициализации закрытой переменной, а в соответствующем объекте. Например, оператор newtype ob5(1), ob6(2); объявляет объект ob5 и обуславливает вызов конструктора newtype, который инициализирует переменную а из ob5 с значением 1. Аналогичные действия осуществляются и для ob6, т.е. переменная а инициализируется с значением 2.
