» » » » Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

На нашем литературном портале можно бесплатно читать книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп, Бьёрн Страуструп . Жанр: Программирование. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале litmir.org.
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Название: Программирование. Принципы и практика использования C++ Исправленное издание
Дата добавления: 22 август 2024
Количество просмотров: 100
Читать онлайн

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту readbookfedya@gmail.com для удаления материала

Программирование. Принципы и практика использования C++ Исправленное издание читать книгу онлайн

Программирование. Принципы и практика использования C++ Исправленное издание - читать бесплатно онлайн , автор Бьёрн Страуструп

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка.
Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие.
Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток.
Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Перейти на страницу:
class="code">  int size() const { return sz; }

  int capacity() const { return space; }

  void resize(int newsize);           // увеличение

  void push_back(double d);

  void reserve(int newalloc);

};

Обратите внимание на то, что этот класс содержит все основные операции (см. раздел 18.3): конструктор, конструктор по умолчанию, копирующий конструктор, деструктор. Он также содержит операции для доступа к данным (индексирование []), получения информации об этих данных (size() и capacity()), а также для управления ростом вектора (resize(), push_back() и reserve()).

19.3. Шаблоны

Однако нам мало иметь вектор, состоящий из чисел типа double; мы хотим свободно задавать тип элементов наших векторов. Рассмотрим пример.

vector<double>

vector<int>

vector<Month>

vector<Window*>          // вектор указателей на объекты класса Window

vector< vector<Record> > // вектор векторов из объектов класса Record

vector<char>

 

 Для этого мы должны научиться определять шаблоны. На самом деле мы с самого начала уже использовали шаблоны, но до сих пор нам не приходилось определять их самостоятельно. Стандартная библиотека содержит все необходимое, но мы не должны полагаться на готовые рецепты, поэтому следует разобраться, как спроектирована и реализована стандартная библиотека, например класс vector и функция sort() (разделы 21.1 и Б.5.4). Это не просто теоретический интерес, поскольку, как обычно, средства и методы, использованные при создании стандартной библиотеки, могут помочь при работе над собственными программами. Например, в главах 21-22 мы покажем, как с помощью шаблонов реализовать стандартные контейнеры и алгоритмы, а в главе 24 продемонстрируем, как разработать класс матриц для научных вычислений.

 

 По существу, шаблон (template) — это механизм, позволяющий программисту использовать типы как параметры класса или функции. Получив эти аргументы, компилятор генерирует конкретный класс или функцию. 

19.3.1. Типы как шаблонные параметры

 

 Итак, мы хотим, чтобы тип элементов был параметром класса vector. Возьмем класс vector и заменим ключевое слово double буквой T, где T — параметр, который может принимать значения, такие как double, int, string, vector<Record> и Window*. В языке С++ для описания параметра T, задающего тип, используется префикс template<class T>, означающий “для всех типов T”.

Рассмотрим пример.

// почти реальный вектор элементов типа T

template<class T> class vector {

  // читается как "для всех типов T" (почти так же, как

  // в математике)

  int sz;      // размер

  T* elem;     // указатель на элементы

  int space;   // размер + свободная память

public:

  vector():sz(0),elem(0),space(0) { }

  explicit vector(int s);

  vector(const vector&);            // копирующий конструктор

  vector& operator=(const vector&); // копирующее присваивание

  ~vector() { delete[] elem; }      // деструктор

  T& operator[](int n) { return elem[n]; } // доступ: возвращает

                                           // ссылку

  const T& operator[](int n) const { return elem[n]; }

  int size() const { return sz; }   // текущий размер

  int capacity() const { return space; }

  void resize(int newsize);         // увеличивает вектор

  void push_back(const T& d);

  void reserve(int newalloc);

};

Это определение класса vector совпадает с определением класса vector, содержащего элементы типа double (см. раздел 19.2.6), за исключением того, что ключевое слово double теперь заменено шаблонным параметром T. Этот шаблонный класс vector можно использовать следующим образом:

vector<double> vd;         // T — double

vector<int> vi;            // T — int

vector<double*> vpd;       // T — double*

vector< vector<int> > vvi; // T — vector<int>, в котором T — int 

 

 Можно просто считать, что компилятор генерирует класс конкретного типа (соответствующего шаблонному аргументу), подставляя его вместо шаблонного параметра. Например, когда компилятор видит в программе конструкцию vector<char>, он генерирует примерно такой код:

class vector_char {

  int sz;      // размер

  char* elem;  // указатель на элементы

  int space;   // размер + свободная память

public:

  vector_char();

  explicit vector_char(int s);

  vector_char(const vector_char&);  // копирующий конструктор

  vector_char& operator=(const vector_char &); // копирующее

                                               // присваивание

  ~vector_char ();            // деструктор

  char& operator[] (int n);   // доступ: возвращает ссылку

  const char& operator[] (int n) const;

  int size() const;           // текущий размер

  int capacity() const;

  void resize(int newsize);   // увеличение

  void push_back(const char& d);

  void reserve(int newalloc);

};

Для класса vector<double> компилятор генерирует аналог класса vector, содержащий элементы типа double (см. раздел 19.2.6), используя соответствующее внутреннее имя, подходящее по смыслу конструкции vector<double>).

 

 Иногда шаблонный класс называют порождающим типом (type generator). Процесс генерирования типов (классов) с помощью шаблонного класса по заданным шаблонным аргументам называется специализацией (specialization) или конкретизацией шаблона (template instantiation). Например, классы vector<char> и vector<Poly_line*> называются специализациями класса vector. В простых ситуациях, например при работе с классом vector, конкретизация не вызывает затруднений. В более общих и запутанных ситуациях конкретизация шаблона очень сильно усложняется. К счастью для пользователей шаблонов, вся эта сложность обрушивается только на разработчика компилятора.

Конкретизация шаблона (генерирование шаблонных специализаций) осуществляется на этапе компиляции или редактирования связей, а не во время выполнения программы.

Естественно, шаблонный класс может иметь функции-члены. Рассмотрим пример.

void fct(vector<string>& v)

{

  int n = v.size();

  v.push_back("Norah");

  // ...

}

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

v.push_back("Norah"), он генерирует функцию

void vector<string>::push_back(const string& d) { /* ... */ }

используя шаблонное определение

template<class T> void vector<T>::push_back(const T& d) { /* ... */ };

Итак, вызову v.push_back("Norah") соответствует конкретная функция. Иначе говоря, если вам нужна функция с конкретным типом аргумента, компилятор сам напишет ее, основываясь на вашем шаблоне.

Вместо префикса template<class T> можно использовать префикс template <typename

Перейти на страницу:
Комментариев (0)