TopSladur.com - Кой е най-големия?
Помогни ни да направим Uroci.net по - богат! Добави урок
Категории Други уроци Adobe Photoshop Adobe Illustrator Adobe Flash Adobe Fireworks DreamWeaver CSS и HTML Corel Draw Image Ready PHP SEO CMS Microsoft Windows Microsoft Word Microsoft Excel PowerPoint Microsoft Access Microsoft Publisher Linux Visual basic JavaScript Ajax 3ds Max Maya 3D C++
C++
Sound Forge Gimp SWiSH

C++ част.7 (Член функции на клас)

C++ » C++
fix3d   трудност:    видян: 6084



Масиви от класове

Един масив от обекти на клас се дефинира по същия начин както и масив от вградените типове данни. Например, tbl и tbl2 дефинират масиви от по 16 обекта на класа String:

const int size = 16;
String tbl[ size ];
String *tbl2 = new String[size];

Достъпът до отделните елементи се осъществява, като се използува индексния оператор както и при вградените типове данни. За да се осигури достъп да определен елемент на масива се прилага оператора за селекция на член на класа след индексния оператор. Ето един пример:

while ( cin >> tbl[ i ] )
tbl[i].display();

Масив от обекти на клас се инициализира като се използуват конструкторите на класа по същия начин, както и за индивидуални обекти. Аргументите на конструктора се задават в инициализационен списък, затворен във фигурни скоби. В случай, че има много аргументи трябва да бъде използуван пълния синтаксис на конструктора; иначе, се възприема както пълния, така и съкратения запис.

Stirng ar1[] = { "phoenix", "crane" };
String ar2[3] = { String(), String(1024),String("string")};
String ar3[2] = { 1024, String( 512 );
};
Screen as[] = { Screen(24, 80,’#’) };

Клас, който дефинира конструктор по подразбиране (т.е. конструктор с празен списък от аргументи) ще може да прилага този конструктор в случай на непълен инициализационен списък. Ако класът не дефинира конструктор по подразбиране инициализационният списък трябва да предлага стойност за всеки елемент на масива. Масив, за който е отделена памет от свободната памет не може да бъде явно инициализиран. Класът трябва или да не дефинира никакъв конструктор или да дефинира конструктор без аргументи.

Преди tbl2 да излезе от обхват е необходимо явното използване на оператора delete за освобождаване на паметта. Обаче, простото написване на

delete tbl2;

не е достатъчно понеже деструкторът на String се прилага само за началния елемент на tlb2. delete не може да знае, че tbl2 не сочи един обект от String, а масив от такива обекти. Програмистът трябва да приложи операторът delete с размера на масива, който tbl2 адресира. Това може да бъде направено така:

delete [ size ] tbl2;

Сега деструкторът на String ще бъде извикан за всеки от елементите на tbl2.

Членове обекти на клас

След като вече сме въвели класа String, нека да дефинираме отново класа Word като заменим члена char* с член от типа String, като запазим съвместимостта с предишния публичен интерфейс.

class Word {
public:
Word();
Word( char*, int = 0 );
Word( String&, int = 0 );

private:
int occurs;
String name;
};

Сега за всеки обект на Word трябва да бъдат викани два конструктора - този на самия клас и другия за члена от клас String. В този случай трябва да бъдат разгледани два въпроса:

1. Дефиниран ли е ред за извикване на конструкторите? И ако е дефиниран, какъв е?
2. Как програмистът би могъл да изпрати аргументи за конструктора на члена от тип клас?

Дефиниран е ред за извикване на конструкторите. Конструкторите на членовете на класа винаги се изпълняват преди конструктора на класа, който ги съдържа. В случай, че има много членове, които са обекти на класове, редът на извикване на конструкторите съответства на реда на членовете в декларацията. (Редът на деструкторите е обратен).

// first String::String( char * )
// then Word::Word( char * ) Word flower( "iris" );

Аргументите се изпращат до конструкторите чрез инициализационен списък на член - списък, от двойки име/аргумент, отделени със запетаи. Например,

Word::Word( char *s, int cnt ) : name( s ) { occurs = cnt; }

Инициализационният списък на член съответствува на сигнатурата на конструктора и се отделя чрез двуеточие. Всеки член може да бъде споменат еднократно в списъка. Инициализационният списък на член може да се явява само в дефиницията на един конструктор; той не може да бъде зададен в декларацията му. В предходния пример на name се изпраща указателя към низ s, който на свой ред се подава като аргумент на конструктора на String. За член данните от вградените типове също могат да бъдат зададени стойности в инициализационния списък. Например, в следния пример occurs се инициализира със стойността на cnt:

Word::Word( char *s, int cnt ) : name( s ), occurs( cnt ) {}

Изпълнението на един конструктор преминава през три фази - на инициализация и присвояване. Когато тялото на конструктора е празно няма фаза на присвояване. Например,

class Simple { public:
Simple( int, float );
private:
int i ;
float f;
};

Simple::Simple( int ii, float ff ) : i(ii), f(ff)
// initialization {} // assignment

Фазата на присвояването започва с изпълнението на тялото на конструктора. Неявна инициализация се случва при наличието на член от тип клас, който дефинира конструктор, който не изисква аргументи. Инициализационният списък прави инициализационната фаза явна. Няма да има инициализационна фаза в случай, че конструкторът на Simple е дефиниран така:

Simple::Simple( int ii, float ff ) {
i = ii;
f = ff; // assignment phase }

В повечето случаи разгранираването на фазите за инициализация и присвояване при изпълнението на един конструктор е прозрачно за програмиста. Обработването на const и псевдонимният член данни на класа е пример, при който разграничаването не е очевидно. Инициализационният списък е само механизъм, чрез който const и псевдонимните член данни на класа могат да бъдат инициализирани. Следната реализация на конструктор, например, не е правилна:

class ConstRef { public:
ConstRef( int ii );
private:
int i;
const int ci;
int &ri;
};

ConstRef::ConstRef( int ii )
{ // assignment
i = ii;// ok
ci = ii; // error: cannot assign to a const
ri = i; // error: ri is uninitialized }

Когато тялото на конструктора започне да се изпълнява трябва вече да е завършила инициализацията на всички константи и псевдоними. Това може да бъде направено чрез задаването им в инициализационния списък. Например,

ConstRef::ConstRef( int ii ) : ci( ii ), ri( i )
// initialization
{ // assignment
i = ii; }

Няма ограничение аргументът за инициализация да бъде прост идентификатор или константа. Той може да бъде произволен сложен израз. Например,

class Random { public:
Random( int i ) : val( seed ( i ) ) {}
int seed( int );

private:
int val;
}

Аргументът за инициализация на член обект на клас може да бъде друг обект от неговия клас.

Word::Word( String &str, int cmt )
: name ( str ), occurs( cnt )
{} String msg( "hello" );
Word greetings( msg );

Всеки член обект на клас трябва да присъствува в инициализационния списък ако конструкторът му изисква списък от аргументи. Ако този списък не бъде зададен ще се издаде съобщение за грешка по време на компилация. Класът SynAntonym, например, съдържа три члена обекти на класове: wd, обект на класа Word, и synonym и antonym, обекти на класа String. Всички обекти на класа Word изискват поне един аргумент от тип char* или от тип String&. Инициализационният списък трябва да предлага списък от аргументи за wd.

class SynAntonym { public:
SynAntonym(char* s) : wd(s) {}
SynAntonym(char* s1, char* s2, char* s3) : wd(s1),
synonym(s2), antonym(s3) {}
~SynAntonym();

private:
String synonym;
Word wd;
String antonym;
};

SynAntonym sa1( "repine" );
SynAntonym sa2( "cause", "origin", "effect" );

Редът за извикване на конструкторите за sa1 и sa2 е следният:

1. Според реда на декларациите в тялото на класа се извиква консруктора за всеки член клас:
String(); // synonym String member
String( "repine" ); // String member of wd
Word( "repine" ); // wd Word member
String(); // antonym String member

// sa1( "repine" );
String( "oridin" ); // synonym String member
String( "cause" ); // String member of wd
Word( "cause" ); // wd Word member
String( "effect" ); // antonym String member
// sa2( "cause", "oridin", "effect" );

2. Извиква се конструктора на външния клас.

Когато един член обект на клас съдържа член обект на клас правилата за подреждане на извикването на конструкторите се прилагат рекурсивно. Редът на обръщенията към деструкторите е обратен на този на обръщенията към конструкторите. Т.е. деструкторите за външния клас се извикват преди тези на членовете обекти на клас. Ако има много обекти на класове редът на обръщенията към деструкторите е обратен на реда на декларациите на членовете обекти на клас.

Упражнение 7-2. Ето една схематична дефиниция на класа Buffer:
#inlcude "String.h"
class Buf
{ public: // ...
private: String buf; };

Декларациите могат да приемат някоя от следните форми:

Stirng s1;
Buf();
Buf( 1024 );
Buf( s1 );

Реализирайте множеството на конструкторите и деструкторите.

Един важен абстрактен тип данни е бинарното дърво. По-долу е представена схема на една реализация на класа бинарно дърво за цели стойности. Реализирането на този клас ще бъде развито от упражненията до края на този подраздел и в другите раздели на тази глава.

class BinTree;
class INode
{ // private class
friend class BinTree;
int val;
BinTree *left;
BinTree *right;
};

class BinTree
{ public: // ... public intrface
private:
INode *node;
};

Едно бинарно дърво може да бъде празно (възелът му сочи 0) или да сочи INode. Всеки INode се състои от три члена: цяла стойност, ляв наследник и десен наследник. Всеки наследник е празен или сочи към бинарно дърво.

Упражнение 7-3. Разгледайте предимствата и недостатъците на дефинирането на класа INode като личен клас.
Упражнение 7-4. Дефинирайте конструктор(и) и деструктор на класа INode.
Упражнение 7-5. Дефинирайте конструктор(и) и деструктор на класа BinTree.
Упражнение 7-6. Разгледайте проекта, избран в упражнение 7-4 и 7-5.


Страници: «1 2 3 4 5 6 7 »

Регистрирайте се, за да добавите коментар

реклама

© Всички права запазени. 2006-2008. Created by: Site.bg
Препоръчваме: IT Новини | Кино и игри | Диплома.бг | Paparak.bg | Тунинг Портал | uchenik.com | TRAVEL туризъм | Реферати | AmAm.bg | Иде.ли | Курсови работи | AnimeS-bg.com | Фото Форум | Запознанства | Мрежа от приятели | IT Light | Spodeli.net | Фото-Култ | Dalavera.net | IDG.BG | Teenproblem.net | mucunki.com | Блог - Образование | Fresh-BG.com | Hanovete.com | Bulfleet.com | Mythlands.com | Ohoboho.com | News24 | Казанлък.Com | Atol.bg | Elmaz.com | MobileBulgaria.com | Setcom.bg