Создание автоматических объектов
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

class A

{

int k, double d;

public:

A ( ) = default;

A (const A&) = default;

A& operator= (const A&) = default;

A (int i, double x) : k(i), d{x} {}

};

void foo ()

{

A a; // k==0, d==0.0 – конструктор по умолчанию

A a2 (10, 7.0); //конструктор

A a3 {5, 6.0}; // унифицированная инициализация, тоже что и а2

A a4 = a2; // k==10, d ==7 - конструктор копии!

A a5 = {11, 2.0}; //тоже что и a3

}

 

Выделение памяти под массивы

· new[] выделяет чуть больше памяти чем нужно для размещения всех элементов массива – дополнительно хранится информация о размере массива

int a[] = new int[10];

delete a;    //Неправильно! Удалится только a[0]

delete[] a; //Правильно!

 

· безопасно вызывать delete на нулевом указателе

int *p = 0;

delete p; //Ok!

delete[] p; //Ok!

 

· При создании массива вызываются конструкторы по умолчанию для всех элементов массива.

· При удалении массива вызываются деструкторы для всех элементов массива

 

Ч то происходит при вызове MyClass *p = new MyClass()

1. вызывается operator new (sizeof(MyClass))

2. вызывается конструктор MyClass()

 

При вызо ве delete (p)

1. вызывается деструктор ~MyClass()

2. вызывается operator delete (p)

 

! Вызываемые операторы operator new и operator delete можно перегрузить в классе

 

Ссылки

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

· Ссылка является альтернативным именем объекта ссылки чаще всего используются для указания аргументов функций и возвращаемых значений вообще, и при перегрузке операторов в частности

· T& - ссылка на T; const T& - константная ссылка на T

· ссылку нельзя объявить, ее можно только определить; инициализатором для T& должно быть lvalue типа T

· инициализатор для const T& не обязан быть lvalue и даже иметь тип T!!!

 

Ссылки в С++ служат двум целям:

· Обеспечивают возможность передачи аргументов в функцию без
их копирования в параметры функции

· Обеспечивают возможность возврата из функции lvalue.

 

Значение ссылки нельзя изменить после инициализации, она всегда ссылается на объект, которым была проинициализирована.

 

Программы на C++

Используется классическая схема:

· Исходные тексты программ хранятся в текстовых файлах на диске (*.cpp, *.cc, *.h, *.hpp)

· Единицей компиляции является файл .cpp или .cc

· Файлы .h и .hpp включаются препроцессором перед компиляцией файлов .cpp и .cc

Результатом компиляции являются объектные модули .o или .obj

· Редактор связей (линковщик) используется для компоновки объектных модулей в исполняемые файлы (.exe) либо библиотеки (статические .lib, либо динамические .dll, .ld.so).

· Возможна компоновка модулей на разных языках

 

2. Средства абстракции C++. Структура класса. Статические члены и их инициализация.

"Абстракция данных" это техника программирования. В С++ это по сути возможность создавать пользовательские классы.


Структура класса

Класс задается своим типом (именем класса), информацией о суперклассе и реализуемых интерфейсах, а также своими членами:

· Полями и методами экземпляра (реализуют свойства объекта)

· Статическими полями и методами класса (реализуют собственно свойства и поведение самого класса)

· Внутренними абстракциями (вложенные и внутренние классы и интерфейсы, как правило, не используемые извне класса)

Статические переменные-члены и методы являются общими для всех экземпляров класса и таким образом, позволяют реализовывать состояние и поведение класса как такового по аналогии с состоянием и поведением объекта

Средства обобщенного программирования – шаблоны классов (родовые компоненты) позволяют порождать родственные классы.

Инстанцирование объектов – создание объекта на основе класса

Инстанцирование шаблонов – создание класса на основе шаблона класса

 

    Статические переменные и их инициализация

Члены класса могут использоваться с ключевым словом static. В данном контексте его значение сходно с тем, которое оно имеет в Си. Когда член класса объявляется как статический, то тем самым компилятору дается указание, что должна существовать только одна копия этого члена, сколько бы объектов этого класса ни создавалось. Статический член используется совместно все­ми объектами данного класса. Все статические данные инициализируются нулями при создании первого объекта, и другая инициализация не предусмотрена.

При объявлении статического члена данных класса этот член не определяется. Вместо этого необходимо обеспечить для него глобальное определение вне класса. Это делается путем нового объявления статической переменной, причем используется оператор области видимости для того, чтобы идентифицировать тот класс, к которому принадлежит переменная. Это необходимо для того, чтобы под статическую переменную была выделена память.

class counter {
static int count;  //static int count = 0; - ОШИБКА!
public:
void setcount(int i) {count = i;};
void showcount () {cout << count << " "; }
};
int counter::count; // определение count







Статические методы

У статических методов есть две интересные особенности. Во-первых, поскольку статические методы не привязаны к объекту, то они не имеют скрытого указателя this ! Здесь есть смысл, так как указатель this всегда указывает на объект, с которым работает метод. Статические методы могут не работать через объект, поэтому и указатель this не нужен.

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

Статические методы можно определять вне тела класса. Это работает так же, как и с обычными методами.

 

class IDGenerator

{

private:

     static int s_nextID; // объявление статической переменной-члена

 

public:

static int getNextID(); // объявление статического метода

};

int IDGenerator::s_nextID = 1;

  int IDGenerator::getNextID() { return s_nextID++; }

 

int main()

{

      for (int count=0; count < 4; ++count)

        std::cout << "The next ID is: " << IDGenerator::getNextID() << '\n';

 

    return 0;

}

 

 

3. Средства инкапсуляции C++. Инкапсуляция и наследование. Друзья.

Классы и инкапсуляция

Существуют следующие уровни доступа к членам класса:

· Открытый (public) – члены с данным уровнем доступа видимы всем клиентам класса

· Защищенный (protected) – члены этого уровня видимы самому классу и его наследникам

· Закрытый (private) – члены данного уровня видны только изнутри самого класса

 

Инкапсуляция и наследование:

Концепции:

· Уточнение (переопределение поведения - перегрузка)

· Расширение (интерфейса абстракции)

· Переиспользование (использование ранее написанного кода, иногда, в данном случае, лучше воспользоваться агрегацией)

Наиболее значимой после классов возможностью ООП является наследование. Это процесс создания новых классов, называемых наследниками или производными классами, из уже существующих или базовых классов. Производный класс получает все возможности базового класса, но может также быть усовершенствован за счет добавления собственных.

class A{

public: int a;

protected: int b;

private: int c;

};

 

class B : public A{};

 

Методы производного класса имеют доступ к членам базового класса, если они имеют спецификатор доступа public или protected. К членам, объявленным как private, доступа нет.

 

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

· public - Права доступа к public и protected членам, наследуемые от базового класса, в производном не меняются.

class D: public B {...}

o Открытые ( public ) и защищенные ( protected ) члены класса B могут использоваться функциями-членами и друзьями класса D, а также могут использоваться функциями-членами и друзьями классов –наследников D.

o Открытые члены B доступны через переменные (ссылки и указатели) типа D

o Всем разрешено осуществлять преобразование типа D в B, D* в B*, D& в B&

 

· protected - Если класс наследовался как protected, то все public и protected члены базового класса становятся protected членами производного.

class D : protected B {...}

o Открытые ( public ) и защищенные ( protected ) члены класса B могут использоваться только функциями-членами и друзьями класса D, а также могут использоваться функциями-членами и друзьями классов – наследников D. Доступ к ним извне через переменные (ссылки, указатели) типа D запрещен

o Только друзья и члены D, а также члены и друзья классов-наследников D могут преобразовывать D* в B* и D& в B& и D в B

 

· private - Если класс наследовался как private, то public и protected члены, наследованные от базового класса, становятся private членами производного класса. В любом случае, private члены базового класса становятся private членами произвольного, причем доступ к этим членам закрыт в производном классе. Чтобы его открыть, производный класс должен быть объявлен другом базового (friend).

       class D : private B {...}:

o Открытые ( public ) и защищенные ( protected ) члены класса B могут использоваться только функциями-членами и друзьями класса D. Доступ к ним извне через переменные (ссылки, указатели) типа D запрещен

o Только друзья и члены D могут преобразовывать D* в B* и D& в B& и D в B

o Наследники класса D “не будут знать” о его базе B

 

Friend функции

Дружественные функции - это функции, которые не являются членами класса, однако имеют доступ к его закрытым членам - переменным и функциям, которые имеют спецификатор private.

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

 

class Auto;

 

class Person

{

public:

Person(std::string n)

{

name = n;

}

void drive(Auto &a);

void setPrice(Auto &a, int price);

 

private:

std::string name;

};

 

class Auto

{

friend void Person::drive(Auto &); //определение друга внутри другого класса

friend void Person::setPrice(Auto &, int price);

public:

Auto(std::string autoName, int autoPrice)

{

name = autoName;

price = autoPrice;

}

std::string getName() { return name; }

int getPrice() { return price; }

 

private:

std::string name; // название автомобиля

int price; // цена автомобиля

};

 

Дата: 2019-02-19, просмотров: 276.