Встраиваемые функции inline
Реализация программы как набора функций удобна с точки зрения разработки программного обеспечения, но вызовы функций приводят к загруженности во время выполнения. В C++ для снижения расходов ресурсов на вызовы функций (особенно небольших функций) предусмотрены встраиваемые (inline) функции. Спецификация inlineперед указанием типа результата в объявлении функции предписывает компилятору сгенерировать копию кода функции в соответствующем месте вызова, чтобы избежать вызова этой функции. Это эквивалентно объявлению соответствующего макроса (директива define сопоставляет символическое имя какой-либо операции). В результате получается множество копий кода функции, вставленных в программу, вместо единственной копии, которой передается управление при каждом вызове функции.
Компилятор может по своему усмотрению игнорировать спецификацию inline,что он делает для всех функций, кроме самых небольших.
Спецификацию inlineцелесообразно применять только для небольших и часто используемых функций. Использование функций inlineможет уменьшить время выполнения программы, но при этом может увеличить ее размер. В целом, применение функций inlineпредпочтительнее объявления макросов, поскольку в данном случае имеется возможность компилятору оптимизировать код.
При использовании функции inlineнадо учитывать, что внесение в нее каких-то изменений может потребовать перекомпиляции всех «потребителей» этой функции — всех модулей, в которых она вызывается. Это может оказаться существенным моментом для развития и поддержки некоторых больших программ.
Пусть, например, вам во многих частях программы приходится вычислять длину окружности, заданной своим радиусом R. Тогда можно оформить эти вычисления, определив встраиваемую функцию:
inline double Circ(double R){return 6.28318 * R;}
Обращение в любом месте программы вида Circ(2)приведет к встраиванию в соответствующем месте кода "6.28318 * 2" (если компилятор сочтет это целесообразным).
3.3. Введение в наследование.
Наследование - это механизм, посредством которого один класс (производный) может наследовать свойства и методы другого класса (базового).
Базовый класс определяет все качества, которые являются общими для всех производных классов.
//Базовый класс
class B
{
int i;
public:
void set_i(int n);
int get_i();
};
//Производный класс D
class D : public B
{
int j;
public:
void set_j(int n);
int mul();
};
После имени класса D стоит двоеточие, за которым стоит ключевое слово public и имя класса B. Это означает, что класс D будет наследовать все компоненты класса B. Само ключевое слово public информирует компилятор о том, что т.к. B будет наследоваться, то все открытые элементы базового класса будут открытыми элементами производного класса. Однако все закрытые элементы базового класса остаются закрытыми.
// Простой пример наследования.
#include <iostream.h>
// Задание базового класса
class base {
int i;
public:
void set_i(int n);
int get_i();
};
// Задание производного класса
class derived : public base {
int j;
public:
void set_j(int n);
int mul();
};
// Установка значения i в базовом классе
void base::set_i(int n)
{
i = n;
}
// Возврат значения i в базовом классе
int base::get_i()
{
return i;
}
// Установка значения j в производном классе
void derived::set_j(int n)
{
j = n;
}
// Возврат значения i из base и, одновременно, j из derived
int derived::mul()
{
// производный класс может вызывать функции-члены базового класса
return j * get_i();
}
main()
{
derived ob;
ob.set_i(10); // загрузка i в base
ob.set_j(4); // загрузка j в derived
cout << ob.mul(); // вывод числа 40
return 0;
}
Важно! При определении mul() вызывается функция get_i()- базового класса base, а не производного derived, что указывает на то, что открытые члены базового класса становятся открытыми членами производного. Но в функции mul() вместо прямого доступа к i, необходимо вызывать get_i(), потому что закрытые члены базового класса(i) остаются закрытыми для производных классов. Дополнительным вариантом является использование описания данных класса как protected.