#include
using namespace std;
class MyString
{
private:
char* Buffer;
public:
// Конструктор
MyString(const char* Initiallnput)
{
if(Initiallnput != NULL)
{
Buffer = new char [strlen(Initiallnput) + 1];
strcpy(Buffer, Initiallnput);
}
else
Buffer = NULL;
}
20
21 // Конструктор копий
12 MyString(const MyString& CopySource)
■3 { _ i
15
16
if(CopySource.Buffer != NULL)
{
Buffer = new char [strlen(CopySource.Buffer) + 1]; strcpy(Buffer, CopySource.Buffer);
}
else
2D Buffer = NULL;
}
52
^MyString ()
{
if (Buffer != NULL)
2 6
|
delete [] Buffer;
|
28
|
}
|
/
|
int GetLength()
4D{
return strlen(Buffer);
42
43
44 const char* GetStringO
{
return Buffer;
}
};
49
53 class Human
{
private:
int Age;
bool Gender;
MyString Name;
public:
Human(const MyString& InputName, int InputAge, bool InputGender)
: Name(InputName), Age (InputAge), Gender(InputGender) {}
int GetAge ()
{
return Age;
}
};
66
int main ()
{
MyString FirstMan ("Adam") ;
'0 MyString FirstWoman("Eve");
'1
|
cout
|
«
|
"sizeof(MyString)
|
=
|
" «
|
sizeof(MyString)
|
«
|
endl;
|
'2
|
73
|
cout
|
«
|
"sizeof(FirstMan)
|
=
|
" «
|
sizeof(FirstMan)
|
«
|
endl;
|
74
|
cout
|
«
|
"sizeof(FirstWoman)
|
= " «
|
sizeof(FirstWoman)
|
« endl;
|
75
240 ЗАНЯТИЕ 9. Классы и объекты
Human FirstMaleHuman(FirstMan, 25, true);
Human FirstFemaleHuman(FirstWoman, 18, false);
cout « "sizeof(Human) = " « sizeof(Human) << endl;
80: cout « "sizeof(FirstMaleHuman) = " « sizeof(FirstMaleHuman)
« endl;
cout << "sizeof(FirstFemaleHuman) = " « sizeof(FirstFemaleHuman) << endl;
82:
return 0;
}
Результат
sizeof(MyString) = 4
fcizeof(FirstMan) = 4
sizeof(FirstWoman) = 4
sizeof(Human) = 12
sizeof(FirstMaleHuman) = 12
sizeof(FirstFemaleHuman) = 12
Анализ
Пример, конечно, длинноват, поскольку он содержит класс M y S t r in g , представленный
ранее в листинге 9.9 (правда, без большинства операторов вывода текста), и вариант клас са Human, который использует тип M y S t r i n g для хранения имени (Name), а также имеет новый параметр типа b o o l для пола (G ender).
Приступим к анализу вывода. Как можно заметить, результат выполнения опера
тора s i z e o f () для класса совпадает с таковым для объекта класса. Следовательно,
s i z e o f ( M y S t r i n g ) — то же самое, что и s i z e o f ( F i r s t M a n ) , поскольку количество
байтов, использованных классом, по существу фиксируется во время компиляции и из вестно уже при разработке класса. Не удивляйтесь, что размер в байтах объектов F i r s t - Man и F ir s t W o m a n одинаков, несмотря на то, что один содержит имя Adam, а другой Eve, поскольку они хранятся в переменной M y S t r i n g : : B u f f e r , которая фактически является указателем типа c h a r * , размер которого составляет 4 байта (на моей 32-разрядной систе ме) и не зависит от объема данных, на которые он указывает.
Попробуйте вычислить размер типа Human вручную, который составляет 12. Стро
ки 53 -55 свидетельствую т, что класс Human содерж ит атрибуты типа i n t , b o o l и
M y S t r i n g . Чтобы освежить в памяти размер в байтах используемых встроенных типов, обратитесь к листингу 3.4. Таким образом, тип i n t использует 4 байта, тип b o o l — 1 байт, тип M y S t r i n g — 4 байта на системе автора, что никак не дает в итоге 12, который отображен в выводе. Дело в том, что на результат оператора s i z e o f () влияют дополнение до границ слова и другие факторы.
Чем структура отличается от класса
Ключевое слово s t r u c t осталось со времен языка С, и во всех практических целях оно обрабатывается компилятором C++ практически так же, как ключевое слово c l a s s . Раз личия кроются в заданном по умолчанию модификаторе доступа ( p u b lic или p r iv a t e ) ,
Объявление друзей класса
|
241
|
гогда разработчик ничего не указывает. По умолчанию, если ничего не указано, члены ггруктуры являются открытыми (p u b lic ), а члены класса — закрытыми ( p r iv a te ) , и если не определено иное, то члены структуры остаются открытыми при наследовании базовой ггруктуры, а у класса — закрытыми. Наследование рассматривается на занятии 10, “Реа лизация наследования”.
Вариант структуры класса Human из листинга 9.12 был бы следующим:
struct Human
{
конструктор, открытый по умолчанию (поскольку никакой
спецификатор доступа не упомянут)
Human(const MyString& InputName, int InputAge, bool InputGender) : Name(InputName), Age (InputAge), Gender(InputGender) {}
int GetAge ()
{
return Age;
}
private:
int Age;
bool Gender;
MyString Name;
Как можно заметить, структура Human очень похожа на класс Human и создание экзем пляра объекта структуры очень похоже на таковое у класса:
Human FirstMan("Adam", 25, true); // экземпляр структуры Human
Объявление друзей класса
Класс не разреш ает доступ извне к своим закрытым переменным-членам и методам. Это правило не относится к тем классам и функциям, которые при помощи ключевого слова f r i e n d объявлены дружественными (friend), как можно заметить в листинге 9.13.
ЛИСТИНГ 9.13. Использование ключевого слова friend, позволяющее внешней
функции DisplayAge () обращаться к закрытым переменным-членам____________________
#include
#include
using namespace std;
class Human
{
private:
string Name;
int Age;
9:
friend void DisplayAge(const Human& Person);
1 1 :
public:
Human(string InputName, intInputAge)
242 ЗАНЯТИЕ 9. Классы и объекты
{
Name = InputName;
Age = InputAge;
}
};
19:
void DisplayAge(const Humans Person)
21: {
cout « Person.Age« endl;
}
24:
int main()
{
HumanFirstMan("Adam", 25);
cout « "Accessing private member Age via friend: ";
DisplayAge(FirstMan);
30:
return 0;
}
Результат
Accessing private member Age via friend: 25
Анализ
С трока 10 содерж ит объявление, указы ваю щ ее компилятору, что функции D isp la y A g e () в глобальной области видимости разрешен специальный доступ к закры
тым членам класса Human. Закомментировав строку 10, вы сразу получите ошибку компи ляции в строке 22.
Как и функции, внешние классы также могут быть объявлены дружественными, как показано в листинге 9.14.
ЛИСТИНГ 9.14. Использование ключевого слова friend, позволяющее внешнему вспомогательному классу обращаться к закрытым переменным-членам__________________
Do'stlaringiz bilan baham: |