Помогни ни да направим Uroci.net по - богат! Добави урок

C++ част.8 (Обектно-ориентирано)

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



Стандартни преобразования

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

Извлечен обект от клас, псевдоним или указател явно се преобразуват в съответния публичен базов тип клас. Например:

ff( ZooAnimal& );
ff( Screen& );// ff( ZooAnimal& )ff( yinYang );*

Указател към произволен тип клас явно се преобразува в указател от тип void

*.ff( Screen& );
ff( void* );// ff( void* ) ff( yinYang );

Преобразуване на обект от базов клас, псевдоним или указател в съответния тип извлечен клас не се прилага. Например, при следващото обръщение не може да се осъществи съпоставяне:

ff( Bear& );ff( Panda& );
ZooAnimal za;ff( za ); // error : no match

Присъствието на два или повече непосредствени базови класове предизвиква маркирането на обръщението като двузначно. Например, Panda се извлича едновременно от Bear и Endangered. И двете преобразования на Panda изискват едно и също действие. Тъй като и двете преобразувания са възможни, обръщението е грешно.

ff( Bear& );ff( Endangered& );
ff( yinYang ); // error : ambiguous

За да бъде осъществено обръщението, програмистът трябва явно да укаже в него:

ff( Bear(yinYang));

Извлеченият клас се разглежда като по-близък до неговия непосредствен базов клас отколкото до един по-отдалечен базов клас. Следващото обръщение не е двузначно, макар че и в двата образеца се изисква стандартно преобразуване. Panda се третира по-скоро като вид Bear, отколкото като вид на ZooAnimal от алгоритъма за съпоставяне на аргументи.

ff( ZooAnimal& ); ff( Bear& );// ff( Bear& ); ff( yinYang );

Това правило се разширява да включва и void*. Например, дадена е следната двойка презаредими функции:

ff( void* );ff( ZooAnimal* );

Аргументът от тип Panda* се съпоставя с ZooAnimal*.

Дефинирани от потребителя преобразувания

Дефинираното от потребителя преобразуване може да бъде конструктор с един аргумент или оператор за явно преобразуване. Дефинираните от потребителя преобразувания се прилагат само ако не може да се направи точно съпоставяне или не се открие стандартно преобразуване. За тази част от параграфа нека осигурим ZooAnimal с две потребителски дефинирани преобразувания:

class ZooAnimal
{public:
ZooAnimal( long );// conversion : long ==> ZooAnimal
operator char*();// conversion : ZooAnimal ==> char*
// ...
};

Дадена е следната двойка презаредими функции:

ff( ZooAnimal& );
ff( Screen& );

Обръщение с фактически параметър от тип long ще бъде осъществено чрез образеца на ZooAnimal чрез извличане на потребителски дефинирано преобразувание:

long lval;// ff( ZooAnimal& )
ff( lval );

Какво ще стане, ако обръщението е с аргумент int? Например,

ff( 1024 ); // ???

Не може да се направи нито точно съпоставяне, нито съпоставяне чрез стандартни преобразувания. Има винаги едно приложимо потребителски дефинирано стандартно преобразуване. Проблемът е в това, че конструкторът за преобразуване на ZooAnimal очаква стойност от тип long,а не int. Алгоритъмът за съпоставяне на аргументи ще приложи стандартно преобразуване за намирането на приложимо потребителски дефинирано преобразуване. В случая, 1024 се преобразува да бъде от тип long, за да се възприеме от конструктора на ZooAnimal. Обръщението се осъществява чрез образеца на ZooAnimal.

Дефинирано от потребителя преобразуване се прилага само когато друго преобразуване не е възможно. Ако образецът на ff() беше деклариран да възприема предварително дефиниран тип, операторът за преобразуване на ZooAnimal нямаше да бъде викан. Например,

ff( ZooAnimal& );
ff( char );// ff( char );
long lval;
ff( lval );

В този случай е необходимо явно указване в обръщението за да се осъществи обръщение към образец на ZooAnimal:

ff( ZooAnimal(lval));// ff( ZooAnimal& )

В следващия пример се прилага операторът за преобразуване в char* на ZooAnimal тъй като няма стандартно преобразуване от обект на базов клас в обект на извлечения клас.

ff( char* );
ff( Bear& );
ZooAnimal za;// za ==> char* // ff( char* ) ff( za );

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

ff( Panda* );
ff( void* );
// za ==> char* ==> void
// ff( void* )
ff( za );

Операторите за преобразуване (но не и конструкторите) се онаследяват по същия начин като другите членове на класа. И Bear, и Panda наследяват char* операторът за преобразуване на ZooAnimal. Например,

ff( char* );
ff( Bear* );
Bear yogi;
Bear pBear = &yogi;// ff( char )ff( yogi );// ff( pBear ) ff( pBear );

Ако съпоставянето е възможно чрез прилагането на две или повече потребителски дефинирани преобразувания, обръщението е двузначно и предизвиква грешка по време на компилация. Преобразуващите конструктори и операторите за преобразуване имат едно и също предимство. Ако може да бъде приложен по един образец от всеки тип, обръщението е двузначно. Например, нека Endangered дефинира оператор за преобразуване от тип int:

class Endangered {
public:
operator int();// conversion : Endangered ==> int
// ...};

Тогава ако Extinct дефинира преобразуващ конструктор, който възприема псевдоним на обект от класа Endangered, както следва

class Extinct {
public:
Extinct( Endangered& );
// ...
};

Следващото обръщение е двузначно. И операторът за преобразуване на Endangered и преобразуващият конструктор на Extinct могат да осъществят съпоставяне.

ff( Extinct& );
ff( int );
Endangered e;
ff( e ); // error : ambiguous

Тук има втори пример на двузначност при извикване на потребителски дефинирано преобразуване. В този случай преобразуващите конструктори на SmallInt и BitVector са еднакво приложими - обръщението се маркира като грешно.

class SmallInt {
public:
SmallInt( int );// conversion : int ==> SmallInt
// ...
};

class BitVector {
BitVector( unsigned long );// conversion : unsigned long ==> BitVector
// ...};
ff( SmallInt& );
ff( BitVector& );
ff( 1 ); // error : ambiguous


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

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


Калдейта ЕООД - © 2003-2010. Всички права запазени.
Препоръчваме: Национален Бизнес | Bomba.bg | IT Новини | Диплома.бг | TRAVEL туризъм | Реферати | AmAm.bg | Иде.ли | Курсови работи | Фото Форум | Spodeli.net | Фото-Култ | Atol.bg | Elmaz.com | MobileBulgaria.com | Казанлък.Com