Определение класса в языке C++ и создание его объекта

Класс - это производный структурированный тип, введенный программистом на основе уже существующих типов. Другими словами, механизм классов задает некоторую структурированную совокупность типизированных данных и позволяет определить набор операций над этими данными.

Общий синтаксис класса можно определить с помощью конструкции:

class имя_класса { список_компонентов };
  • имя_класса - произвольно выбираемый идентификатор
  • список_компонентов - определения и описания типизированных данных и принадлежащих классу функций. Компонентами класса могут быть данные, функции, классы, перечисления, битовые поля и имена типов. Вначале для простоты будем считать, что компоненты класса - это типизированные данные (базовые и производные) и функции.
  • Заключенный в фигурные скобки список компонентов называют телом класса.
  • Телу класса предшествует заголовок. В простейшем случае заголовок класса включает слово class и имя.
  • Определение класса всегда заканчивается точкой с запятой.

Итак, принадлежащие классу функции мы будем называть методами класса или компонентными функциями. Данные класса - компонентными данными или элементами данных класса.

Вернемся к определению: класс - это тип, введенный программистом. А, так как, каждый тип служит для определения объектов, определим синтаксис создания объекта класса.

имя_класса имя_объекта;

Определение объекта класса предусматривает выделение участка памяти и деление этого участка на фрагменты, соответствующие отдельным элементам объекта.

Способы доступа к компонентам класса.

Существует несколько уровней доступа к компонентам класса. Рассмотрим основные:

  • public - члены класса открыты для доступа извне.
  • private - члены класса закрыты для доступа извне.

По умолчанию все переменные и функции, принадлежащие классу, определены как закрытые (private). Это означает, что они могут использоваться только внутри функций-членов самого класса. Для других частей программы, таких как функция main(), доступ к закрытым членам запрещен. Это, кстати, единственное отличие класса от структуры - в структуре все члены по умолчанию - public.

С использованием спецификатора доступа public можно создать открытый член класса, доступный для использования всеми функциями программы (как внутри класса, так и за его пределами).

class имя_класса
{
     закрытые переменный и функции;
     защищенные члены данных; защищенные конструкторы; защищенные методы;
public:
     открытые переменные и функции;
     общедоступные свойства; общедоступные члены данных; общедоступные конструкторы; общедоступный деструктор; общедоступные методы;
} список имен объектов;

Синтаксис для доступа к данным конкретного объекта заданного класса (как и в случае структур), таков:

имя_объекта.имя_члена класса;

Пришло время примера…

# include <iostream>
using namespace std;
class Test{
	// так как спецификатор доступа не указан
	// данная переменная будет по умолчанию закрыта
	// для доступа вне класса (private)
	int one;
 
	// спецификатор доступа public
	// все члены, идущие после него
	// будут открыты для доступа извне
public: 
 
	// инициализировать переменные в классе 
	// при создании запрещено, поэтому мы определяем
	// метод, реализующий данное действие
	void Initial(int o,int t){
		one=o;
		two=t;
	}
 
	// метод показывающий переменные класса 
	// на экран
	void Show(){
		cout<<"\n\n"<<one<<"\t"<<two<<"\n\n";
	}
	int two;
};
void main(){
 
	// создается объект с типом Test
	Test obj;
	// вызывается функция, инициализирующая его свойства
	obj.Initial(2,5);
 
	// показ на экран
	obj.Show(); // 2 5
 
	// прямая запись в открытую переменную two
	// с переменной one такая запись невозможна, так
	// как доступ к ней закрыт
	obj.two=45;
 
	// снова показ на экран
	obj.Show(); // 2 45
 
}

Вышеописанный пример вполне интуитивно прост, однако, выделим один из главных моментов - переменные класса нет необходимости передавать в методы класса в качестве параметров, так как они видны в них автоматически.

Внутри класса функции-члены могут вызывать друг друга и обращаться к к переменным членам, не используя оператор точка(.) Этот оператор необходим, лишь когда обращение к функциям и переменным-членам осуществляется извне класса.

Указатели на объекты. Доступ к членам объекта можно осуществлять и через указатель на объект. В этом случае применяется операция стрелка (→).

Оператор :: называется оператором разрешения области видимости (scope resolution operator). Т.е. создается шаблон класса и в нем шаблоны методов класса, а сами методы описываются вне описания класса.

class stack {
 
  int stck[SIZE];
 
  int tos;
 
public:
 
  void init();
 
  void push(int i);
 
  int pop();
 
};
 
 
 
void stack::init()
 
{
 
  tos = 0;
 
}
 
 
 
void stack::push(int i)
 
{
 
  if(tos==SIZE) {
 
    cout << "Stack is full.\n";
 
    return;
 
  }
 
  stck[tos] = i;
 
  tos++;
 
}

Константный метод объекта

Говорят, что метод объекта обладает свойством неизменности (константности), если после его выполнения состояние объекта не изменяется.Если не контролировать свойство неизменности, то его обеспечение будет целиком зависеть от квалификации программиста. Если же "неизменный" метод в процессе выполнения будет производить посторонние эффекты, то результат может быть самым неожиданным,отлаживать и поддерживать такой код очень тяжело.

Язык С++ позволяет пометить метод как константный. При этом неконстантные методы объекта запрещается использовать в теле помеченного метода, и в контексте этого метода ссылки на сам объект и все его поля будут константны. Для обозначения константности, используется модификатор const.

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

Давайте, рассмотрим пример класса с константными методами:

# include <iostream>
# include <string.h>
using namespace std;
class Personal
{
public:
	// конструктор с параметрами
	// мы выделяем здесь память
	// однако в нашем примере нет
	// ни деструктора, ни конструктора
	// копирования - единственная цель,
	// которую мы преследуем показать 
	// работу константного метода
	Personal(char*p,char*n,int a){
        name=new char[strlen(n)+1];
		if(!name){
			cout<<"Error!!!";
			exit(0);
		} 
		picture_data=new char[strlen(n)+1];
		if(!picture_data){
			cout<<"Error!!!";
			exit(0);
		}
		strcpy(picture_data,p);
		strcpy(name,n);
		age=a;
	}
 
	// Группа константных методов
	// внутри них невозможно
	// изменить какое-то из свойств
	const char*Name()const{
		return name;
	}
	int Age()const{
		return age;
	}
	const char*Picture()const{
		return picture_data;
	}
 
	void SetName(const char*n){
		strcpy(name,n);
	}
	void SetAge(int a){
		age=a;
	}
	void SetPicture(const char*p){
		strcpy(picture_data,p);
	}
 
private:
	char*picture_data; // путь к фотографии
	char*name; // имя
	int age; // возраст
};
 
void main(){
	Personal A("C:\\Image\\","Ivan",23);
	cout<<"Name: "<<A.Name()<<"\n\n";
	cout<<"Age: "<<A.Age()<<"\n\n";
	cout<<"Path for picture: "<<A.Picture()<<"\n\n";
	A.SetPicture("C:\\Test\\");
	A.SetName("Leonid");
	A.SetAge(90);
	cout<<"Name: "<<A.Name()<<"\n\n";
	cout<<"Age: "<<A.Age()<<"\n\n";
	cout<<"Path for picture: "<<A.Picture()<<"\n\n";
}

В данном примере методы Name, Age, Picture объявлены константными. Кроме того, можно наблюдать и использование константных указателей: параметр методов SetName и SetPicture, возвращаемое значение методов Name и Picture. Компилятор обеспечит проверку того, что реализация константных методов не имеет побочных эффектов в виде изменения состояния объекта, реализующего класс Personal. Как только обнаружится попытка выполнить запрещенную операцию, компилятор сообщит об ошибке.

PQ VPS сервера в 28+ странах.