236
if (pkey == pbeg){
pbeg = pbeg->next; pbeg->prev = 0;}
else if (pkey == pend){
pend = pend->prev; pend->next = 0;}
else {
(pkey->prev)->next = pkey->next;
(pkey->next)->prev = pkey->prev;}
delete pkey; return true;}
return false;
}
Егер
List
шаблонын құрамдас типтегі емес, қолданушы анықтаған типтегі
мəліметтерді сақтау үшін қолдану керек болса, онда осы типтің сипаттамасын-
да ағымға шығару (бұл туралы «Қолданушы анықтаған ағымдар мен типтер»
бөлімінде, 305 б. жазылған) жəне теңдікке тексеру операцияларының асыра
жүктелуін қосу керек, ал егер оның өрістері үшін жадыны динамикалық бөлу
қолданылса, онда меншіктеу операциясын да қосу керек болады.
Шаблон синтаксисін анықтау кезінде оған типтер мен үлгілермен қоса, ай-
нымалыларды да беруге болатынын айтылған. Олар бүтін немесе тізбелік типті,
сонымен қатар объектіге немесе функцияға нұсқауыштар немесе сілтемелер
болуы мүмкін. Олар шаблон тұлғасының тұрақтылық өрнекті пайдалануға бо-
латын кез келген жерінде қолданылуы мүмкін. Мысал ретінде ұзындығы мен
типі белгілі жады блогын қамтитын класс шаблонын құрайық:
template
class Block{
public:
Block(){p = new Type [kol];}
~Block(){delete [] p;}
operator Type *();
protected:
Type * p;
};
template
Block :: operator Type *(){
return p;
}
Класс шаблондарын құру мен жөндеп түзетуден кейін тақырыптық
файлдарға орналастырған ыңғайлы болады.
Класс шаблондарын қолдану
Шаблондар көмегімен нақты бір кластың нақты объектісін құру үшін (бұл
үрдіс инстанциялау деп аталады) объектіні сипаттау кезінде шаблон атауынан
кейін бұрыштық жақша ішінде оның аргументтері тізіліп жазылады:
237
шаблон_атауы <аргументтер>
объект_атауы [(конструктор_параметрлері)];
Аргументтер шаблонның параметрлерімен сəйкес келуі тиіс. Шаблонның
аргументтерімен бірге жазылған атауын кластың нақтыланған атауы ретінде
қабылдауға болады. Объектілерді өткен бөлімде сипатталған шаблондар
бойынша құру мысалдары:
List List_int;
List List_double;
List List_monstr;
Block buf;
Block stado;
Шаблонның келісім бойынша параметрлерін қолдану кезінде аргументтер
тізімі бос болып шығуы мүмкін, мұндайда бұрыштық жақшаларды тастап ке-
туге болмайды:
template class String;
String<>* p;
Егер шаблонның параметрі специализациясы бар шаблон болса, ол ин-
станциялау кезінде ескеріледі (шаблондардың специализациясы туралы келесі
бөлімде жазылады):
template class A{
// Бастапқы шаблон
int x;
};
template class A { // Шаблонның
// специализациясы
long х;
};
template class V> class C{
V y;
V z;
};
...
C c;
Бұл мысалда
С<А>
ішінде
V
бастапқы шаблонды қолданады, сол
себепті
с.у.х
типі
int
болады, ал
V
шаблон специализациясын
қолданады, сондықтан
с.z.х
типі
long
болады.
Бүтін типті айнымалылар болып табылатын формалды параметрлердің
орындарында тұрақтылық өрнектер болу керек.
Шаблонның көмегімен объектілерді құрғаннан кейін олармен қарапайым
кластардың объектілерімен бірдей жұмыс істеуге болады, мысалы:
for (int i = 1; i<10; i++) List_double.add(i * 0.08);
List_double.print();
238
// ----------------------------------
for (int i = 1; i<10; i++) List_monstr.add(i);
List_monstr.print();
// ----------------------------------
strcpy(buf, "Өте маңызды хабарлама");
cout << buf << endl;
Кластардың шаблондарын қолдануды жеңілдету үшін
typedef
көмегімен
типтерге қайта атау беруді жүзеге асыруға болады:
typedef List Ldbl;
Ldbl List_double;
Класс шаблондарының специализациясы
Шаблон бойынша құрылатын кластың немесе функцияның əрбір
нұсқасының базалық кодтары бірдей болады; тек шаблон параметрлерімен
байланысы бар элементтер өзгереді. Мұндайда əртүрлі мəліметтер типтері
үшін құрылатын нұсқалардың жұмыс істеу тиімділігі де əркелкі болуы мүмкін.
Егер қандай да бір мəліметтер типі үшін бұрынғысынан тиімдірек код
бар болса, онда бұл тип үшін жеке əдістердің арнайы жүзеге асырылуын
қарастыруға болады немесе класс шаблонын толығымен қайта анықтау (спе-
циализациялау) керек болады.
Əдісті специализациялау үшін оның тақырыбында нақты мəліметтер
типін көрсету арқылы код нұсқасын анықта алу керек. Мысалы, егер
Достарыңызбен бөлісу: