{
this-> health+=health; /* использование this */
monstr::ammo+=ammo; /* использование операции:: */
}
Использование параметра this не дает ощутимого преимущества при программировании, так как данные конкретного объекта уже доступны в принадлежащих классу функциях по именам. Удобным и необходимым он становится, когда в теле принадлежащей классу функции требуется явно задать адрес, для которого она была вызвана.
Ниже приведён пример кода, в котором использование this делает код более читаемым и удобным для написания.
Пример 2
class MyClass{
void foo(){
MyClass *ptr = new MyClass(*this);
//Тут некоторый код
delete ptr;
}
};
int main(){
MyClass obj;
}
Без указателя this этот код выглядел бы примерно так:
Пример 3
class MyClass{
void foo(MyClass* obj){
MyClass *ptr = new MyClass(*obj);
//Тут некоторый код
delete ptr;
}
public:
void init(MyClass* obj){
foo(obj);
}
};
int main(){
MyClass obj;
obj.init(&obj);
}
Статические элементы классов
Статическими компонентами называются компоненты класса, которые объявлены с модификатором static. Статические компоненты класса являются частью класса, но не включаются в объекты этого класса. Имеется ровно одна копия статических полей класса. Она является общей для всех объектов данного класса. Статические поля никогда не дублируются.
|
|
Особенности:
память под статические поля выделяется один раз при их инициализации. Независимо от числа созданных объектов (и даже при их отсутствии) инициализируются статические поля с помощью операции доступа к области действий, а не с помощью оператора выбора (т.е. определение статического поля должно быть описано вне функции).
Пример 1
Class A
{
public:
static int count; /* Объявление в классе */
};
int A::count; /* Объявление в глобальной области. По умолчанию инициализируется нулем */
int A::count = 10; /* Пример инициализации произвольным значением */
Статические поля доступны как через имя класса, так и через имя объекта.
Пример 2
A*a,b;
cout<<A::count<<a->count<<b.count;
На статические поля распространяется действие спецификаторов доступа, следовательно описанные как private статические поля нельзя изменять с помощью операций доступа к области действия. Это можно сделать только с помощью статических методов. Память, занимаемая статическим полем, не учитывается при определении размера объекта с помощью операции sizeof. Принципиально любой метод класса может обратиться к статическому полю и изменить его значение. Но существует возможность обращения к статическому полю при отсутствии объектов данного класса. Такой доступ осуществляется с помощью статических компонентных функций, которые объявляются со спецификатором static. Статическая функция не ассоциируется с каким-либо объектом и не получает параметра this. Она не может без указателя объекта обращаться к нестатическим полям класса. При необходимости ссылка на конкретный объект может быть передана в списка параметров и тогда статическая функция может обратиться к нестатическим полям следующим образом:
|
|
<имя объекта>.<имя нестатического поля класса>
При обращении к статическому компоненту класса, являющемуся принадлежностью всех объектов данного класса, можно вместо имени объекта указать имя класса.
<класс>::<компонент>
Статические методы
Предназначены для обращения к статическим полям класса. Обращение к статическим методам производится так же, как и к статическим полям, а именно:
а) через имя класса,
б) через имя объекта, если он уже создан.
Пример 1
Class A
{
static int count; /* поле count - скрытое */
public:
static void int_count() {count++}
};
A::int count; /* определение в глобальной области*/
Void f()
{
A.a;
/* a.count++ - нельзя, так как поле count скрытое.
Изменение поля count выглядит следующим образом: */
a.inc_count();
/*или:*/
A::inc_count();
}
Пример 2
Class point
{
int x, y, color; /* нестатическое поле */
static int obj_count; /* Статическое поле - счетчик обращений */
public:
point();
static void draw_point(point &p); /* статическая функция */
};
int point::obj_count = 0; /* инициализация статического поля */
void point::draw_point(point &p) /* имя объекта передано в списке параметров */
{
putpixel(p.x, p.y, p.color);
obj_count++; /* обращение к статическому и нестатическому полю */
}
Рекомендации по составу класса
Класс, как тип, определяемый пользователем, должен содержать скрытые поля (private) и следующие функции:
· конструкторы, определенные как инициализирующиеся объекты класса;
· методы, реализующие свойства класса (методы, возвращающие значения скрытых полей класса описываются с модификатором const, который указывает, что они не должны изменять значения этих полей);
· операции, позволяющие копировать, присваивать, сравнивать объекты и производить над ними другие действия, требуемые по сути класса;
· необходим еще функциональный класс исключений, используемый для сообщений об ошибках, с помощью генерации исключительных ситуаций.
Могут также использоваться функции, которые работают с классом или несколькими классами через интерфейс (т.е. доступ к скрытым полям им не требуется). Эти функции можно описать вне классов, чтобы не перегружать интерфейс. Чтобы обеспечить логическую связь, можно поместить их в общее с этим классом пространство имен.
Пример 1
Namespace staff
{
class monstr{...};
class hero{...};
void interact(hero, monstr);
}
Пример 2
class String {
public:
// набор конструкторов
// для автоматической инициализации
// String strl; // String()
// String str2("literal"); // String(const char*);
// String str3(str2); // String(const String&);
String();
String(const char*);
String(const String&);
// деструктор
~String();
// операторы присваивания
// strl = str2
// str3 = "a string literal"
String& operator=(const String&);
String& operator=(const char*);
// операторы проверки на равенство
// strl == str2;
// str3 == "a string literal";
bool operator==(const String&);
bool operator==(const char*);
// перегрузка оператора доступа по индексу
// strl[ 0 ] = str2[ 0 ];
char& operator[](int);
// доступ к членам класса
int size() { return _size; }
char* c_str() { return _string; }
private:
int _size;
char *_string;
}
Глава 4. Дружественные классы и функции