Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Int rn; //индекс числа записейСодержание книги
Поиск на нашем сайте
//БД из трех Trecord определяется объект с именем db шаблонного класса типа TDatabase и задается TRecord в качестве класса, замещающего Т в шаблоне. Выражение в скобках (3) — инициализатор db, передаваемый конструктору класса TDatabase. TDatabase<TRecord> db(3); //БД из трх указателей объявляется объект dbp класса TDatabase, состоящий из трех указателей на TRecord TDatabase<TRecord*> dbp(3); //указатель на БД TDatabase<TRecord> *pdb; //указатель на БД указаелей TDatabase<TRecord*> *ppdb; cout<< "\n\nDatabase of 3 TRecords\n"; //вызывается функция GetRecord(O) //для доступа к записи с индексом 0 // Затем в строке вызывается ф-ция- //член Assign() этого объекта для //задания строкового значения db.GetRecord(0).Assign("GeorgeWashington"); db.GetRecord(1).Assign("John Adams"); db.GetRecord(2).Assign("Thomas Jefferson"); for(rn=0; rn<=2;rn++) {cout << db.GetRecord(rn).GetName() << '\n';} cout << "\n\nDatabase of 3 TRecord pointers\n"; dbp.GetRecord(0) = new TRecord("George Bush"); dbp.GetRecord(1) = new TRecord("Ronald Reagan"); dbp.GetRecord(2) = new TRecord("Jimmy Carter"); for (rn = 0; rn <= 2; rn++) cout << dbp.GetRecord(rn)->GetName() << '\n'; cout << "\n\nPointer to database of 3 TRecords\n"; pdb = new TDatabase<TRecord>(3); pdb->GetRecord(0).Assign("John Adams"); pdb->GetRecord(1).Assign("Thomas Jefferson"); pdb->GetRecord(2).Assign("Aaron Burr"); for (rn = 0; rn <= 2; rn++) cout << pdb->GetRecord(rn).GetName() << '\n'; cout << "\n\nPointer to database of 3 TRecord pointers\n"; ppdb = new TDatabase<TRecord *>(3); ppdb->GetRecord(0) = new TRecord("Dan Quayle"); ppdb->GetRecord(1) = new TRecord("George Bush"); ppdb->GetRecord(2) = new TRecord("Walter Mondale"); for (rn = 0; rn <= 2; rn++) cout << ppdb->GetRecord(rn)->GetName() << '\n'; getch(); return 0; } После включения заголовочного файла DB.H (строка 3), содержащего объявление шаблонного класса TDatabase, в программе объявляется класс TRecord — один из объектов для запоминания в TDatabase. Класс TRecord очень прост, в нем объявлен в качестве данных-членов только символьный массив name. Однако TRecord на самом деле может быть произвольным классом, так как в классе TDatabase не делается никаких предположений о типе сохраняемых объектов. В строках 22—25 демонстрируются четыре способа создания объектов класса с помощью шаблона класса. В строке TDatabase<TRecord> db(3); определяется объект с именем db шаблонного класса типа TDatabase и задается TRecord в качестве класса, замещающего Т в шаблоне. Выражение в скобках (3) — инициализатор db, передаваемый конструктору класса TDatabase. Вы можете также создать базу данных из других значений, для этого не обязательно использовать классы. Например, вы можете определить базу данных из 100 вещественных значений двойной точности следующим образом: TDatabase<double> dbd(100); Поскольку класс TDatabase написан для сохранения объектов произвольных типов, он называется контейнерным классом. Обычно, наилучшие контейнерные классы являются полностью обобщенными, хотя этот идеал часто трудно достичь. В строках 23-25 демонстрируется создание других экземпляров шаблонного класса. В строке 23 объявляется объект dbp класса TDatabase, состоящий из трех указателей на TRecord, в строке 24 — указатель pdb на объект класса TDatabase с незаданным числом объектов типа TRecord. Эти примеры могут покрыть большую часть объектов, которые вы можете захотеть создать на основе других шаблонов класса. В программе объект класса TDatabase используется так же, как и любой другой не шаблонный объект. Например, в строке 28 db.GetRecord(0).Assign("George Washington"); вызывается функция GetRecord(O) для доступа к записи с индексом 0. Затем в строке вызывается функция-член Assign() этого объекта для задания строкового значения. В строках 34-55 демонстрируется использование других объектов класса TDatabase. Особенно любопытна строка 35: dbp.GetRecord(O) = new TRecorcK"George Bush"); Поскольку функция GetRecordO возвращает ссылку на объект, она может использоваться в левой части оператора присваивания. В данном случае создается новый объект TRecord, а его адрес присваивается в базе данных записи с индексом нуль, ссылку на которую возвращает функция GetRecordO. Обратите внимание, что во всех этих примерах вам не надо информировать компилятор с помощью приведения типов о типах данных, используемых классом TDatabase. Несмотря на обобщенную природу шаблонов, можно избежать приведения типов и, тем не менее, создавать классы, которые могут поддерживать множество различных типов данных. Вероятно, лучше не писать шаблонные классы с чистого листа. Вместо этого вы можете написать класс TDatabase, использующий заданные объекты TRecord. Затем, после отладки TDatabase, вы можете преобразовать его в универсальный шаблон. Преобразование обычных классов в шаблоны подобным способом помогает также определить истинно обобщенные свойства класса — требование, которое часто является наиболее сложным аспектом создания полезных шаблонов. Разное Все компьютерные языки имеют ценные, но редко используемые средства. Скорее всего, вы не захотите пользоваться следующими приемами слишком часто, тем не менее одно или несколько этих средств C++ могут оказаться полезными для вас. Указатели на функции-члены Вы можете ссылаться на функции-члены класса с помощью указателей, но не так, как вы ссылаетесь на обычные функции (см. главу 9). Функции-члены вызываются для объектов класса, и они получают скрытый указатель this. Поэтому адресация функций-членов с помощью указателей требует нового подхода. Указатель на функцию-член связан с именем ее класса. Например, для класса TFirstClass вы можете объявить функцию-член следующим образом: double (TFirstClass::*myfnptr)(void); Это означает, что указатель myfnptr ссылается на функцию-член класса TFirst Class, не имеющую параметров и возвращающую вещественное значение двойной точности. Для объявления myfnptr указателем, ссылающимся на функцию, которая ничего не возвращает и имеет два целочисленных параметра, вы можете написать следующее: void (TFirstClass::*myfnptr)(int, int); В этих объявлениях не указывается конкретно, на какие функции-члены ссылается указатель myfnptr, задается только вид функции, адрес которой может быть присвоен указателю. Остается создать объект класса и присвоить адрес его члена, имеющего соответствующий вид, указателю. В листинге 15.14 демонстрируются основные действия, необходимые для объявления и использования указателей на функции-члены класса. Листинг 15.14. MFNPTR.CPP (указатели на функции-члены) «include <iostream.h> «include <iomanip.h> class TFirstClass { private: int count; public: TFirstClassO { count = 0; } int Access(void); int (TFirstClass::*myfnptr)(void); main() int i; TFirstClass fc; cout «"\nCall Access the normal way:\n"; for (i = 0; i < 9; i++) cout «setw(8) «dec «f с AccessO; cout «"\n\nCall Access via the member function pointer\n"; myfnptr = &TFirstClass::Access; for (i = 0; i < 9; i++) cout «setw(8) «dec «(fc.*myfnptr)(); cout «"\n\nMember function pointer and a dynamic instance\n" TFirstClass *fp = new TFirstClass; for (i = 0; i < 9; i++) cout «setw(8) «dec «(fp->*myfnptr)(); return 0;} int TFirstClass::Access(void) { return count++; } В строке 12 myfnptr объявляется указателем на функцию-член класса TFirstClass, не имеющую аргументов и возвращающую целочисленное значение. Указатель может ссылаться на любые функции-члены класса, имеющие подобный вид. В функции main() в строке 17 объявляется объект fc класса TFirstClass, в строке 21 вызывается функция-член AccessO класса TFirstClass для объекта fc обычным способом. (Функция AccessO только инкрементиру-ет и возвращает закрытый член класса — должно же в программе хоть что-нибудь выполняться!) В строке 25 демонстрируется вызов функции-члена AccessO с помощью указателя myfnptr. Для инициализации указателя в строке 23 указателю myfnptr присваивается адрес функции-члена AccessO класса TFirstClass. Вы можете также заменить объявление указателя (строка 12) и присваивание (строка 23) одним оператором, глобальным или локальным в функции main(): int (TFirstClass::*myfnptr)(void) = &TFirstClass::Access; При вызове по указателю функции-члена вы должны придерживаться следующих двух правил. • Обращайтесь к объекту класса. • Заключайте в круглые скобки вызов функции. Например, если п — целочисленная переменная, и fс — объект класса TFirstClass, следующая строка присвоит п результат функции AccessO: n = (fc.*myfnptr)(); Двухсимвольное выражение.* называется оператором ссылки на член и служит для разыменования указателя на функцию-член объекта класса. Круглые скобки в выражении (fc.*myfnptr) необходимы, поскольку оператор вызова функции О имеет более высокий приоритет, чем.*. Оператор, приведенный выше, в точности соответствует более распространенному n = fc. AccessO; Можно также вызывать функции-члены с помощью указателей, когда объекты адресуются другими переменными-указателями. Например, вернемся к строкам 27-29 в модуле MFNPTR (листинг 15.14). Сначала указателю fp присваивается адрес нового объекта класса TFirstClass. Затем в выражении (fp->*myfnptr)(); в операторе вывода в поток в строке 29 вызывается функция-член AccessO для объекта, адресованного указателем fp. Трехсимвольное выражение ->* — другой вид оператора ссылки на член. Опять же, необходимы дополнительные скобки, поскольку операция О имеет более высокий приоритет, чем ->*. Предыдущий оператор в точности соответствует следующему: fp->Access(); В дополнение к адресации функций-членов указателями, можно также ссылаться на другие открытые члены класса. Например, если бы класс TFirstClass имел открытый член типа double с именем balance, вы могли бы объявить указатель на этот член следующим образом: double TFirstClass:: *dataPtr; Указатель dataPtr объявляется для адресации любых открытых данных-членов в классе TFirstClass, имеющих тип вещественных значений двойной точности. Для инициализации указателя следует использовать оператор, подобный следующему: dataPtr = &TFirstClass::balance;
Или же можно объявить указатель и присвоить ему адрес члена balance следующим образом: double TFirstClass:: «dataPtr = &TFirstClass:.'balance; В любом случае, указатель dataPtr теперь ссылается на член balance класса TFirstClass. В действительно-1 сти dataPtr не содержит адрес размещения в памяти, вместо этого в нем хранится смещение, по которому член I balance размещается в объекте класса TFirstClass. Остается обратиться к адресованному члену через объект I класса. Следующие операторы, например, инициализируют и отображают значение balance: fc.balance = 1234.56 cout «"\nBalance=" «fc.*dataPtr; Запись fc.*dataPtr аналогична записи, используемой для вызова функции-члена, в ней используется оператор ссылки на член.*. В этом выражении, конечно, не требуются дополнительные круглые скобки, поскольку оно не содержит конфликтующих операторов. Статические члены Статические функции-члены обычно выполняют глобальные действия или инициализируют глобальные данные для всех объектов класса. Для объявления статической функции-члена укажите перед обычным объявлением функции-члена класса ключевое слово static. class TAnyClass { public: static void Globallnit(void); }; Статические функции-члены не могут быть виртуальными. Реализовать статические функции-члены следует так же, как и другие, предварив имя функции именем класса и оператором разрешения области видимости: void TAnyClass::GlobalInit(void) { // Операторы, которые //необходимо выполнить} Статические функции-члены могут выполнять любые операторы, однако они не получают указатель this и не имеют доступа ни к каким данным- или функциям-членам класса. Для вызова статической функции-члена в программе используется не объект, а имя класса: TAnyClass::GlobalInit(); // Вызвать статическую Функцию Globallnit()
Предполагается, что статическая функция-член, подобная GloballnitO, выполняет действия, касающиеся всех объектов типа TAnyClass. В классах также могут объявляться статические данные-члены. Например, в классе class TAnyClass { private: static char с; // Статический член, хранящий данные public: char GetC(void) { return с; } }; член с объявляется закрытым статическим членом класса. (Статические данные-члены также могут быть защищенными и открытыми.) Существует лишь одна копия TAnyClass::с независимо от того, сколько определяется объектов класса TAnyClass в программе. Статические данные-члены должны определяться и инициализироваться в программе, обычно с помощью глобальных объявлений, подобных следующему: char TAnyClass::с = 'q'; В действительности с — глобальная переменная, доступная только функциям-членам TAnyClass. Далее можно определить объект класса TAnyClass, использующий с. Например, следующие операторы определяют объект х и вызывают функцию-член GetC, отображающую символ 'q': TAnyClass x;
|
||||
Последнее изменение этой страницы: 2016-08-01; просмотров: 192; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 52.14.219.203 (0.01 с.) |