1. Trang chủ
  2. » Công Nghệ Thông Tin

A Complete Guide to Programming in C++ part 47 pps

10 222 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Nội dung

SOLUTIONS ■ 439 // // Fract_t.cpp // Testing the class Fraction. // Modules: Fract_t.cpp Fraction.cpp // #include "Fraction.h" int main() { Fraction a(1,3), b(4); cout << "\nSome test results:\n\n"; cout << " a = " << a << endl; cout << " b = " << b << endl; cout << " a + b = " << (a + b) << endl; cout << " a - b = " << (a - b) << endl; cout << " a * b = " << (a * b) << endl; cout << " a / b = " << (a / b) << endl; cout << " a = " << a << endl; cout << " ++a = " << ++a << endl; a += Fraction(1,2); cout << " a+= 1/2; a = " << a << endl; a -= Fraction(1,2); cout << " a-= 1/2; a = " << a << endl; cout << "-b = " << -b << endl; cout << "\nAnd now an input\n"; cin >> a; cout << "\nYour input: " << a << endl; return 0; } This page intentionally left blank 441 Type Conversion for Classes Implicit type conversion occurs in C++ when an expression cannot be compiled directly but can be compiled after applying a conversion rule. The programmer can stipulate how the compiler will perform implicit type conversion for classes by defining conversion constructors and functions. Finally, we discuss ambiguity occurring due to type conversion and how to avoid it. chapter 20 442 ■ CHAPTER 20 TYPE CONVERSION FOR CLASSES Current Class Another Type Converting Constructor Converting- Function // The class Euro defined in the last chapter // contains the following conversion constructors: Euro::Euro( int ); // int -> Euro Euro::Euro( double ); // double -> Euro // The following declarations are now possible: // Conversion constructors Euro my(100), // int-> Euro, your(321.41); // double -> Euro. my = 987.12; // Implicit conversion: // double -> Euro your += 20; // Implicit conversion: // int -> Euro your = Euro(999.99); // Explicit conversion // (constructor style) my = (Euro)123.45; // Explicit conversion // (cast style) your = my; // No conversion When the copy constructor performs a type conversion, a temporary object is first created and this object is used in the assignment. The temporary object is cleaned up later. ✓ NOTE ■ CONVERSION CONSTRUCTORS Possible conversions Converting constructors of class Euro CONVERSION CONSTRUCTORS ■ 443 ᮀ Possible Type Conversions Implicit and explicit type conversion is also performed for classes in C++. As a program- mer, you decide what kind of conversion is permissible. You can allow type conversion between different classes or between classes and fundamental types. Any type conversion involving a class is defined either ■ by a conversion constructor or ■ by a conversion function. A conversion constructor performs type conversion by converting any given type to the type of the current class. A conversion function performs conversion in the opposite direction, that is, it converts an object of the current class to another type—a standard type, for example. ᮀ Conversion Constructors A constructor with a single parameter determines how to form an object of the new class from the argument passed to it. For this reason, a constructor with only one parameter is referred to as a conversion constructor. The copy constructor is an exception to this rule: it creates an object of the same class and does not perform type conversion. Each conversion constructor is placed by the compiler on a list of possible conver- sions. The standard string class contains a constructor that creates a string object from a C string, for example. Example: string::string( const char* ); This allows you to supply a C string as an argument wherever a string object is required. ᮀ Calling a Conversion Constructor Conversion constructors have already been used in several examples; for example, in the Euro class. The compiler uses them to perform implicit and explicit type conversion. Examples: Euro salary(8765.30); salary += (Euro)897.1; // explicit salary += 897.1; // implicit The last statement initially causes a type mismatch. Addition is not defined for a euro and a double value. The compiler therefore activates the conversion constructor to cre- ate a temporary Euro type object from the double value. This object is then added to the value of the salary object. 444 ■ CHAPTER 20 TYPE CONVERSION FOR CLASSES // Euro.h : The class Euro represents a euro. // // . . . class Euro { private: long data; // Euros * 100 + Cents public: Euro( int euro = 0, int cents = 0); Euro( double x); // For conversion from Euro to double: operator double() const { return (double)data/100.0; } // . . . other methods as before. }; // Euro_t.cpp : Testing conversions of class Euro. // #include "Euro.h" // Definition of the class #include <iostream> using namespace std; int main() { cout << " * * * Testing Conversions * * * \n" << endl; Euro salary( 8888,80); double x(0.0); salary += 1000; // implicit int -> Euro salary += 0.10; // implicit double -> Euro x = salary; // implicit Euro -> double x = (double)salary; // explicit Euro -> double x = salary.operator double(); // also possible! // Constructor style is also safe for built-in types: x = double(salary); int i = salary; // Euro -> double -> int // Output: cout << " salary = " << salary << endl; // 9888,90 Euro cout << " x = " << x << endl; // 9888.9 cout << " i = " << i << endl; // 9888 return 0; } ■ CONVERSION FUNCTIONS A converting function for the Euro class Testing conversions CONVERSION FUNCTIONS ■ 445 If you need to convert an object of the current class to another type, you must define a conversion function to do so. This is an operator function that defines how conversion is performed. Conversion functions are also automatically used by the compiler to perform implicit and explicit type conversion. ᮀ Defining Conversion Functions A conversion function is always implemented as a method of the current class. Its name is made up of the operator keyword and the target type to convert to. Example: operator int(void) const; The previous statement declares a conversion function where the target type is int. You may have noticed that the declaration of a conversion function does not contain a return type. This is because the return type is implicitly defined by the target type in the name of the conversion function. The target type can contain multiple keywords, such as unsigned short or const float*. Thus, conversion functions must be written to construct a target type object from the current object,*this, and return the target object. The Euro shown opposite contains a conversion function with a double target type. In other words, the function converts a Euro type object to a floating-point number. Example: double x = oneEuro; // implicit ᮀ Conversion Function versus Conversion Constructor The target type of a conversion function can also be a class. In this case, you must decide whether it is preferable to use a conversion constructor in the target class. If you do not want to modify the target class—perhaps because it is a standard class— a conversion function will perform the task well. ᮀ Standard Type Conversion In addition to user-definable type conversions, the compiler also performs standard type conversions. In the previous example, an int variable is assigned to a euro object by this method. Example: int wholePart = oneEuro; This first converts a Euro object to double and then to int, that is, the cents are trun- cated. 446 ■ CHAPTER 20 TYPE CONVERSION FOR CLASSES // Euro.h : The class Euro represents a euro. // // . . . class Euro { private: long data; // Euros * 100 + Cents public: explicit Euro( int euro = 0, int cents = 0); explicit Euro( double x); // Converting Euro to double: double asDouble() const { return (double)data/100.0;} // No conversion function operator double(), // or as previously seen. }; // Euro_E_t.cpp // Tests explicit conversion of class Euro. // #include "Euro_Ex.h" // Class definition #include <iostream> using namespace std; int main() { Euro salary( 8888.8); // double constructor double x(0.0); /* Now impossible: salary += 1000; // implicit int -> Euro salary += 0.10; // implicit double -> Euro salary = 7777.77; x = salary; // implicit Euro -> double x = (double)salary; // There is no method // operator double(). // The following conversions are ok: salary = Euro( 7777.77); // explicit double -> Euro salary += Euro(1000.10); x = salary.asDouble(); // explicit by method // Euro -> double int i = salary.asDouble(); // Euro -> double -> int return 0; } ■ AMBIGUITIES OF TYPE CONVERSIONS Explicit type conversion for class Euro Testing explicit conversions AMBIGUITIES OF TYPE CONVERSIONS ■ 447 ᮀ Type Conversion Failure Defining a conversion function or conversion constructor can prevent you from compil- ing a program that is otherwise unchanged. The Euro class contains a conversion constructor that converts a double value to euros. This means that the following statement is valid for two objects, wholesale and retail, of the Euro type. Example: retail = wholesale + 46.9; If you now additionally implement the conversion function operator double() that converts a euro to a double value, the previous statement can no longer be com- piled. Since both conversion types double -> Euro and Euro -> double are defined, two possible conversions could be performed: prov2 + Euro(546.9) // To add euros and double(prov2) + 546.9; // To add values // of type double However, the compiler can only perform implicit type conversion if the technique is not ambiguous. If more than one choice is available, the compiler issues an error message. ᮀ Avoiding Implicit Type Conversion You can prevent ambiguities by stating any desired conversions explicitly. This also has the advantage of highlighting type conversions in your source code. Moreover, undesir- able type conversion, which can occur when classes are extended at a later date, can be avoided. In order to ensure that some kinds of type conversion are only performed explicitly, you can use the following techniques: ■ you can use an explicit declaration for the conversion constructor. As the example on the opposite page shows, only explicit calls to the constructor are possible in this case. Example: wholesale + Euro(46.9) // ok ■ implicit type conversions by conversion functions can be prevented by not defin- ing the function, of course. Instead you can use a method of an appropriate name, for example asType(). Type conversion can only be performed by calling this function explicitly. exercise 448 ■ CHAPTER 20 TYPE CONVERSION FOR CLASSES // Fraction.cpp // . . . // To simplify fractions: void Fraction::simplify() { // Divide the numerator and denominator by // the greatest common divisor. if( numerator == 0) { denominator = 1; return; } // Calculating the greatest common divisor // using an algorithm by Euclid. long a = (numerator < 0) ? -numerator : numerator, b = denominator, help; while( b != 0) { help = a % b; a = b; b = help; } // a is the greatest common divisor numerator /= a; denominator /= a; } ■ EXERCISE Method simplify() of class Fraction . The standard string class contains a constructor that creates a string object from a C string, for example. Example: string::string( const char* ); This allows you to supply a C string as an argument. numerator == 0) { denominator = 1; return; } // Calculating the greatest common divisor // using an algorithm by Euclid. long a = (numerator < 0) ? -numerator : numerator, b = denominator, help; while(. previous example, an int variable is assigned to a euro object by this method. Example: int wholePart = oneEuro; This first converts a Euro object to double and then to int, that is, the cents are trun- cated. 446 ■ CHAPTER

Ngày đăng: 06/07/2014, 17:21

TỪ KHÓA LIÊN QUAN