Определение методов класса вне класса — КиберПедия 

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

Типы оградительных сооружений в морском порту: По расположению оградительных сооружений в плане различают волноломы, обе оконечности...

Определение методов класса вне класса

2021-12-07 20
Определение методов класса вне класса 0.00 из 5.00 0 оценок
Заказать работу

В предыдущем классе employee функция была определена внутри самого класса (встроенная (inline) функция). При увеличении функций определение встроенных функций внутри класса может внести беспорядок в описание класса. В качестве альтернативы вы можете поместить прототип функции внутри класса, а затем определить функцию вне класса. Ваше определение класса с прототипом становится следующим:

class employee

{
public:
char name[64];
long employee_id;
float salary;
void show_employee(void); |————————> Прототип функции
};

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

void employee:: show_employee (void) //-------------->Имя класса

{
сout << "Имя: " << name << endl; Имя элемента cout << "Номер служащего: " << employee_id << endl;
cout << "Оклад: " << salary << endl;
};

Как видите, приведенный код предваряется определением функции с именем класса (employee) и оператором глобального разрешения (::). Следующая программа CLASSFUN.CPP помещает определение функции show_employee вне класса, используя оператор глобального разрешения для указания имени класса:

#include <iostream.h>

#include <string.h>

class employee

{
public:
char name [64];
long employee_id;
float salary;
void show_employee(void);
};

void employee::show_employee(void)
{
cout << "Имя: " << name << endl;
cout << "Номер служащего: " << employee_id << endl;
cout << "Оклад: " << salary << endl;
};

void main(void)

{
employee worker, boss;
strcpy(worker.name, "John Doe");
worker.employee_id = 12345;
worker.salary = 25000;
strcpy(boss.name, "Happy Jamsa");
boss.employee_id = 101;
boss.salary = 101101.00;
worker.show_employee();
boss.show_employee();
}

Методы класса

Классы C++ позволяют вашим программам группировать данные объекта и функции объекта (методы), которые оперируют с этими данными, в одной переменной. У вас есть две возможности определения методов объекта. Первая состоит в том, что вы можете включить весь код функции внутрь определения класса. Несмотря на то что включение кода метода в определение класса может представляться удобным, однако, когда классы становятся сложнее и включают несколько методов, операторы функций могут вносить беспорядок в определение классов. Таким образом, многие программы определяют операторы функции вне класса. В определение класса программа должна включать прототип функции, который указывает имя функции, тип возвращаемого значения и типы параметров.

Для определения функции вне определения класса ваша программа должна предварять определение функции именем класса и оператором глобального разрешения, как показано ниже:

return_type class_name::function_name(parameters)
{ // Операторы }

ВТОРОЙ ПРИМЕР

Следующая программа PEDIGREE.CPP создает класс dog, который содержит несколько полей данных и функцию show_breed. Программа определяет функцию класса вне определения самого класса. Затем программа создает два объекта типа dog и выводит информацию о каждой собаке:

#include <iostream.h>

#include <string.h>

class dogs

{
public:
char breed[64];
int average_weight;
int average_height;
void show_dog(void);
};

void dogs::show_breed(void)

{
cout << "Порода: " << breed << endl;
cout << "Средний вес: " << average_weight << endl;
cout << "Средняя высота: " << average_height << endl;
}

void main(void)

{
dogs happy, matt;
strcpy(happy.breed, "Долматин");
happy.average_weight = 58;
happy.average_height = 24;
strcpy(matt.breed, "Колли");
matt.average_weight =22;
matt.average_height = 15;
happy.show_breed();
matt.show_breed();
}

ЧТО ВАМ НЕОБХОДИМО ЗНАТЬ

Программы на C++ широко используют классы. Говоря кратко, классы позволяют вашим программам группировать для определенного объекта его данные и методы (функции), которые оперируют этими данными, в одной переменной. Как видите, классы очень похожи на структуры, которые вы рассматривали в уроке 18. Классы C++ являются основой объектно-ориентированного программирования. Следующие уроки расширяют возможности предоставляемые классами. Упоминавшаяся в этом уроке метка public, по являющаяся в определении класса, делает элементы класса доступными для всей программы. Из урока 22 вы больше узнаете о частных и общих элементах класса. До изучения урока 22 убедитесь, что освоили следующие основные концепции:

    1. В известном смысле объект представляет собой сущность, с которой ваши программы выполняют разные операции.
    2. Программы на C++ представляют объекты посредством классов.
    3. Класс, подобно структуре, содержит элементы. Элементы класса могут хранить информацию (данные) или быть функциями (методами), которые оперируют этими данными.
    4. Каждый класс имеет уникальное имя.
    5. После определения класса вы можете объявлять объекты этого класса, используя имя класса в качестве типа.
    6. Для обращения к элементам класса (как к данным, так и к функциям) ваши программы используют оператор точку.
    7. Программы могут определять функцию класса внутри или вне определения класса. Если вы определяете функцию вне определения класса, вам следует указать имя класса и использовать оператор глобального разрешения, например

25.    Inline Функции

Чтобы избежать расходов на вызов функции, функцию можно описать как inline, а чтобы обеспечить более быстрый доступ к параметрам, их можно описать как register.

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

inline-функция - это функция с модификатором ilnline, код которой компилятор может встроить в место вызова функции. Например

код C++
1:

2:

3:

4:

5:

6:

7:

8:

9:

10:

inline int func(void)

{

return 5;

}

int main(void)

{

int n = func();

//...

}


Компилятор может встроить код функции, примерно так:

код C++
1:

2:

3:

4:

5:

int main(void)

{

int n = 5; // нет функции, есть её код

//...

}


Т.к. вызов функции требует некоторых накладных расходов, то inline-функции могут увеличить эффективность, но приводят к увеличению кода.
inline - это только рекомендация, компилятор сам решает, может он встроить функцию или нет. Сложные функции с операторами ветвления, циклов и т.п. вполне могут быть не встроены.
Например, если определение inline-функции расположено в заголовочном файле, и компилятор не сможет её встроить, то проект скомпилируется, но в каждом модуле, включающем этот заголовок, будет своя копия функции.

"накладные расходы на вызов ф-ции" - не пустой звук! Например, ф-ция которая вычисляет Max из двух-трёх значений, в inline-варианте будет работать на 10-25% быстрее, т.к. не-inline функция потребует создания кадра стека и сопутствующих действий (пролог-эпилог), а inline - "прозрачно", т.е. прямо в коде текущей функции выполнит все свои действия.

26.               Указатель this

В C++ существует специальный указатель this. Для "процедурных программистов" эта тема является довольно "тугой" для понимания, поэтому немного о том, что такое указатель this в контексте нашей серии статей.

Экземпляр объекта, как мы рассматривали в статье "Введение в теорию компиляции. И выведение из неё...", есть семантическое соединение двух сущностей - данных, располагаемых в сегменте данных и методов, располагаемых в сегменте кода. Данные объекта могут изменяться во время жизни объекта, а методы - нет. Методы целиком определяются его статическим типом и все экземпляры данного статического типа разделяют один и тот же экземпляр кода методов имея при этом свой экземпляр данных.

При этом в C++ различаются статические методы класса и нестатические методы класса, причём утверждается, что только нестатические методы класса могут обращаться к нестатическим же данным класса. Что это такое и почему существует это правило?

А правило говорит вот о чём - если класс определяет данные, которые у каждого экземпляра объекта будут индивидуальны, то обращаться к таким индивидуальным данным могут только нестатические методы. Статическим методам к ним обращаться нельзя.

Чем отличаются оба типа методов? Только одним - нестатические методы имеют скрытый параметр, который им подставляет компилятор, когда генерирует вызов - в этом параметре компилятор передаёт адрес структуры данных, соответствующих данному экземпляру объекта. А у статических методов такого параметра нет, поэтому они и не могут адресоваться к индивидуальным данным экземпляра.

Вот этот-то самый указатель, именующий индивидуальную структуру данных для каждого объекта и называется "указатель this". Семантически он соответствует адресу "всего экземпляра объекта". И когда компилятор компилирует код метода класса, то все ссылки на свои данные экземпляра (например, на переменную "x") компилятор по умолчанию трактует как this->x. Т.о. внутри метода класса this есть "указатель на самого себя". Естественно, что внутри каждого экземпляра всякого класса this будет иметь своё значение - его заранее не знает программист, зато - очень хорошо знает компилятор. И его обязательно получит и любой нестатический метод объекта.

Но сам метод - "не обслуживается" this. Методы-то класса всегда разделяются всеми экземплярами класса. И уничтожаются - только данные класса, а методы неуничтожимы. Поэтому вызов конструкции delete this вполне корректен, он заставит метод класса разрушить данный экземпляр данных (объект) класса, но не сам этот метод - другие экземпляры того же класса не пострадают.

Код C++

1 2 3 4 5 6 7 8 class Foo{ public: Foo* GetThis() { // Возвращаем указатель на данный объект return this; } };
 

 

27. Селекторы

Сопоставление шаблонов

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

Чувствительность имен элементов языка документа к регистру определяется языком документа. Например, в HTML-документах имена элементов не зависят от регистра, а в XML-документах - зависят.

В следующей таблице приводятся краткие сведения о синтаксисе селекторов в CSS2:

Шаблон Значение Описано в разделе
* Сопоставляется любому элементу. Универсальный селектор
E Сопоставляется любому элементу E (т.е. элементу типа E. Селекторы типа
E F Сопоставляется любому элементу F, который является потомком элемента E. Селекторы потомков
E > F Сопоставляется любому элементу F, который является дочерним элементом элемента E. Селекторы дочерних элементов
E:first-child Сопоставляется элементу E, если он является первым дочерним элементом своего родительского элемента. Псевдокласс:first-child
E:link E:visited Сопоставляется элементу E, если он является привязкой гиперссылки, направляющей к документу, которой еще не был просмотрен (:link) или уже был просмотрен (:visited). Псевдоклассы ссылок
E:active E:hover E:focus Сопоставляется элементу E во время определенных действий пользователя. Динамические псевдоклассы
E:lang(c) Сопоставляется элементу E, если он присутствует в разговорном языке (язык документа указывает, каким образом определяется разговорный язык). Псевдокласс:lang
E + F Сопоставляется любому элементу F, которому непосредственно предшествует элемент E. Селекторы сестринских элементов
E[foo] Сопоставляется любому элементу E с набором атрибутов "foo" (независимо от значения). Селекторы атрибутов
E[foo="warning"] Сопоставляется любому элементу E, у которого значение атрибута "foo" в точности равно "warning". Селекторы атрибутов
E[foo~="warning"] Сопоставляется любому элементу E, у которого значением атрибута "foo" является список значений, разделенных пробелами, и одно из этих значений в точности равно "warning". Селекторы атрибутов
E[lang|="en"] Сопоставляется любому элементу E, атрибут "lang" которого имеет список значений, разделенных знаками дефиса, начинающийся (слева) со значения "en". Селекторы атрибутов
DIV.warning Только в HTML. Значение аналогично значению DIV[class~="warning"]. Селекторы классов
E#myid Сопоставляется любому элементу E, атрибут ID которого равен "myid". ID-селекторы

Синтаксис селекторов

Простой селектор - это либо селектор типа, либо универсальный селектор, непосредственно за которым в произвольном порядке может следовать несколько селекторов атрибутов, ID-селекторов или псевдоклассов. Простой селектор сопоставим, если сопоставимы все его компоненты.

Селектор представляет собой последовательность из одного или нескольких простых селекторов, между которыми расположены комбинаторы. Комбинаторами могут служить пробелы, символы ">" и "+". Между комбинатором и простыми селекторами может находиться произвольное количество пробелов.

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

К последнему в последовательности простому селектору может быть добавлен один псевдоэлемент. В этом случае информация о стиле будет применяться только к части каждой области применения.

Группировка

Если в нескольких селекторах используются одни и те же объявления, их можно сгруппировать в список, разделив запятыми.

В данном примере собраны три правила с одинаковыми объявлениями. Таким образом, запись

H1 { font-family: sans-serif }H2 { font-family: sans-serif }H3 { font-family: sans-serif }

эквивалентна следующей:

H1, H2, H3 { font-family: sans-serif }

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

Универсальный селектор

Универсальный селектор, при написании обозначаемый символом "*", сопоставляется имени элемента любого типа. Он сопоставляется любому одиночному элементу в дереве документа.

Если универсальный селектор является не единственным компонентом простого селектора, то символ "*" может быть опущен. Например, записи:

  • *[LANG=fr] и [LANG=fr] эквивалентны.
  • *.warning и.warning эквивалентны.
  • *#myid и #myid эквивалентны.

Селекторы типов

Селектор типа сопоставляется названию типа элемента языка документа. Селектор типа сопоставляется каждому экземпляру данного типа в дереве документа.

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

H1 { font-family: sans-serif }

Селекторы потомков

Иногда бывает необходимо, чтобы селекторы сопоставлялись элементу, который является потомком некоторого другого элемента в дереве документа (например, элементам EM, содержащимся в элементе H1). Селекторы потомков позволяют устанавливать такие ассоциации в шаблоне. Селектор потомков состоит из двух и более селекторов, разделенных пробелом. Селектор потомков вида "A B" сопоставим, если элемент B является произвольным потомком некоторого своего предка A.

Например, рассмотрим следующие правила:

H1 { color: red }EM { color: red }

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

<H1>Данный заголовок <EM>очень</EM> важен</H1>

Приведем тот же пример, дополнив предыдущие правила еще одним, устанавливающим синий цвет текста всякий раз, когда элемент EM находится внутри элемента H1:

H1 { color: red }EM { color: red }H1 EM { color: blue }

Третье правило в следующем фрагменте будет сопоставляться элементу EM:

<H1>This <SPAN class="myclass">headline is <EM>very</EM> important</SPAN></H1>

Следующий селектор:

DIV * P

сопоставляется элементу P, который является потомком второго и более старшего поколения элемента DIV. Обратите внимание на пробелы с обеих сторон звездочки "*".

Селектор, который фигурирует в следующем правиле, объединяющем селекторы потомков и селекторы атрибутов, сопоставляется любому элементу, который, во-первых, имеет заданный атрибут "href" и, во-вторых, находится внутри элемента P, который, в свою очередь, находится внутри элемента DIV:

DIV P *[href]

Поделиться с друзьями:

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

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



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.075 с.