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

ANSI/ISO C++ Professional Programmer''''s Handbook phần 3 ppt

24 245 0

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 24
Dung lượng 68,68 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Secondly, a conversion operator takes no arguments.Conversion operators can convert their object to any given type, fundamental and user-defined alike: struct DateRep //legacy C code //

Trang 1

Secondly, a conversion operator takes no arguments.

Conversion operators can convert their object to any given type, fundamental and user-defined alike:

struct DateRep //legacy C code

//transmit date object as a binary stream to a remote client

int ret_stat = transmit_date; //using legacy communication API

return 0;

}

Standard Versus User-Defined Conversions

The interaction of a user-defined conversion with a standard conversion can cause undesirable surprises and sideeffects, and therefore must be used with caution Examine the following concrete example

A non-explicit constructor that takes a single argument is also a conversion operator, which casts its argument to

an object of this class When the compiler has to resolve an overloaded function call, it takes into consideration suchuser-defined conversions in addition to the standard ones For example

f(5.f); //OK, calls void f(Numeric) Numeric's constructor

//converts argument to a Numeric object

'Suppose you add, at a later stage, another overloaded version of f():

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 3 - Operator Overloading

file:///D|/Cool Stuff/old/ftp/1/1/ch03/ch03.htm (8 von 15) [12.05.2000 14:45:47]

Trang 2

void f (double);

Now the same function call resolves differently:

f(5.f); // now calls f(double), not f(Numeric)

This is because float is promoted to double automatically in order to match an overloaded function signature.This is a standard type conversion On the other hand, the conversion of float to Numeric is a user-defined

conversion User-defined conversions rank lower than standard conversions -in overload resolution; as a result, thefunction call resolves differently

Because of this phenomenon and others, conversion operators have been severely criticized Some programmingschools ban their usage altogether However, conversion operators are a valuable and sometimes inevitable toolfor bridging between dual interfaces, as you have seen

Postfix and Prefix Operators

For primitive types, C++ distinguishes between ++x; and x++; as well as between x; and x ; Under somecircumstances, objects have to distinguish between prefix and postfix overloaded operators as well (for example, as anoptimization measure See Chapter 12, "Optimizing Your Code") Postfix operators are declared with a dummy intargument, whereas their prefix counterparts take no arguments For example

class Date

{

public:

Date& operator++(); //prefix

Date& operator (); //prefix

Date& operator++(int unused); //postfix

Date& operator (int unused); //postfix

};

void f()

{

Date d, d1;

d1 = ++d;//prefix: first increment d and then assign to d1

d1 = d++; //postfix; first assign, increment d afterwards

}

Using Function Call Syntax

An overloaded operator call is merely "syntactic sugar" for an ordinary function call You can use the explicit

function call instead of the operator syntax as follows:

bool operator==(const Date& d1, const Date& d2);

void f()

{

Date d, d1;

bool equal;

d1.operator++(0); // equivalent to: d1++;

d1.operator++(); // equivalent to: ++d1;

equal = operator==(d, d1);// equivalent to: d==d1;

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 3 - Operator Overloading

file:///D|/Cool Stuff/old/ftp/1/1/ch03/ch03.htm (9 von 15) [12.05.2000 14:45:47]

Trang 3

Date&(Date::*pmf) (); //pointer to member function

pmf = & Date::operator++;

}

Consistent Operator Overloading

Whenever you overload operators such as + or -, it might become necessary to support the corresponding += and -=operators as well The compiler does not do that for you automatically Consider the following example:

d1 = d1 + d2; //fine; uses overloaded + and default assignment operator

d1 += d2; //compile time error: 'no user defined operator += for class Date'Theoretically, the compiler could synthesize a compound operator += by combing the assignment operator and theoverloaded + operator so that the expression d1 += d2; is automatically expanded into d1 = d1+d2;

However, this is undesirable because the automatic expansion might be less efficient than a user-defined version ofthe operator An automated version creates a temporary object, whereas a user-defined version can avoid it

Moreover, it is not difficult to think of situations in which a class has an overloaded operator +, but does not haveoperator += intentionally

Returning Objects by Value

For the sake of efficiency, large objects are usually passed to or returned from a function by reference or by theiraddress There are, however, a few circumstances in which the best choice is still to return an object by value

Operator + is an example of this situation It has to return a result object, but it cannot modify any of its operands Theseemingly natural choice is to allocate the result object on the free store and return its address Nevertheless, this isnot such a good idea Dynamic memory allocation is significantly slower than local storage It also might fail andthrow an exception, which then has to be caught and handled Even worse, this solution is error prone because it isunclear who is responsible for deleting this object the creator or the user?

Another solution is to use a static object and return it by reference For example

Year& operator + (const Year& other) const; //returns a reference to

//a local static Year

int getYear() const;

void setYear(int y);

};

Year& Year::operator + (const Year& other) const

{

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 3 - Operator Overloading

file:///D|/Cool Stuff/old/ftp/1/1/ch03/ch03.htm (10 von 15) [12.05.2000 14:45:47]

Trang 4

static Year result;

result = Year(this->getYear() + other.getYear() );

return result;

}

Static objects solve the ownership problem, but they are still problematic: On each invocation of the overloadedoperator, the same instance of the static object is being modified and returned to the caller The same object can bereturned by reference to several more users, who do not know that they are holding a shared instance that has justbeen modified behind their back

Finally, the safest and most efficient solution is still to return the result object by value:

bool operator == (const Month& m1, const Month &m2);

It is possible to use the overloaded operator == to compare a plain int value and a Month object due to the implicitconversion of int to Month For example

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 3 - Operator Overloading

file:///D|/Cool Stuff/old/ftp/1/1/ch03/ch03.htm (11 von 15) [12.05.2000 14:45:47]

Trang 5

This works fine, but it i's inefficient: The argument n is first converted to a temporary Month object, which is thencompared with the object June You can avoid the unnecessary construction of a temporary object by definingadditional overloaded versions of operator ==:

bool operator == (int m, const Month& month);

bool operator == (const Month& month, int m);

Consequently, the expression June == n will now invoke the following overloaded operator:

bool operator == (const Month& month, int m);

This overloaded version does not create a temporary object, so it's more efficient The same performance

considerations led the C++ Standardization committee to define three distinct versions of operator == for

std::string (see Chapter 10, ""STL and Generic Programming"") and other classes of the Standard Library.'

Overloading Operators for Other User-Defined types

You can overload an operator for enum types as well For example, it may be useful to overload operators such as ++and so that they can iterate through the enumerator values of a given enum type You can do it like this:

return d = Monday; //rollover

int temp = d; //convert to an int

return d = static_cast<Days> (++temp);

}

int main()

{

Days day = Monday;

for (;;) //display days as integers

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 3 - Operator Overloading

file:///D|/Cool Stuff/old/ftp/1/1/ch03/ch03.htm (12 von 15) [12.05.2000 14:45:47]

Trang 6

Overloading the Subscripts Operator

For various classes that contain arrays of elements, it's handy to overload the subscript operator to access a singleelement Remember always to define two versions of the subscript operator: a const version and a non-constversion For example

void * operator [] (int index) { return ptr_array[index];}

const void * operator [] (int index) const { return ptr_array[index];}};

void f(const Ptr_collection & pointers)

{

const void *p = pointers[0]; //calls const version of operator []

if ( p == 0)

return;

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 3 - Operator Overloading

file:///D|/Cool Stuff/old/ftp/1/1/ch03/ch03.htm (13 von 15) [12.05.2000 14:45:47]

Trang 7

#include <iostream>

using namespace std;

class increment

{

//a generic increment function

public : template < class T > T operator() (T t) const { return ++t;}

associativity and the precedence of an operator cannot be altered Built-in operators have an interface, consisting ofthe number of operands to which the operator can be applied, whether the operator modifies any of its operands, andresult that is returned by the operator When you are overloading an operator, it is recommended that you conform toits built-in interface

Conversion operators are a special type of overloaded operators They differ from ordinary overloaded operators intwo respects: They do not have a return value and they do not take any arguments

ANSI/ISO C++ Professional Programmer's Handbook - Chapter 3 - Operator Overloading

file:///D|/Cool Stuff/old/ftp/1/1/ch03/ch03.htm (14 von 15) [12.05.2000 14:45:47]

Trang 9

ANSI/ISO C++ Professional Programmer's

Handbook

Contents

4 Special Member Functions: Default Constructor, Copy Constructor, Destructor,

And Assignment Operator

Simulating Virtual Constructors

Covariance of Virtual Member Functions

ANSI/ISO C++ Professional Programmer's Handbook - 4 - Special Mem nstructor, Copy Constructor, Destructor, And Assignment Operator

file:///D|/Cool Stuff/old/ftp/1/1/ch04/ch04.htm (1 von 24) [12.05.2000 14:46:07]

Trang 10

Simulating Inheritance Of Assignment Operator

every class object has four special member functions: default constructor, copy constructor, assignment operator, and

destructor If these members are not explicitly declared by the programmer, the implementation implicitly declares them.This chapter surveys the semantics of the special member functions and their role in class design and implementation.This chapter also examines several techniques and guidelines for effective usage of the special member functions

Constructors

A constructor is used to initialize an object A default constructor is one that can be invoked without any arguments Ifthere is no user-declared constructor for a class, and if the class does not contain const or reference data members, theimplementation implicitly declares a default constructor for it

An implicitly-declared default constructor is an inlinepublic member of its class; it performs the initializationoperations that are needed by the implementation to create an object of this type Note, however, that these operations donot involve initialization of user-declared data members or allocation of memory from the free store For example

indeterminate value after obj has been constructed

ANSI/ISO C++ Professional Programmer's Handbook - 4 - Special Mem nstructor, Copy Constructor, Destructor, And Assignment Operator

file:///D|/Cool Stuff/old/ftp/1/1/ch04/ch04.htm (2 von 24) [12.05.2000 14:46:07]

Trang 11

This is because the synthesized default constructor performs only the initialization operations that are required by theimplementation not the programmer to construct an object In this case, C is a polymorphic class An object of thistype contains a pointer to the virtual function table of its class The virtual pointer is initialized by the implicitly-definedconstructor.

Other implementation-required operations that are performed by implicitly-defined constructors are the invocation of abase class constructor and the invocation of the constructor of embedded objects The implementation does not declare aconstructor for a class if the programmer has defined one For example

Calling An Object's Member Function From Its Constructor

Because the virtual pointer is initialized in the constructor before any user-written code, it is safe to call member

functions (both virtual and nonvirtual) of an object from its constructor It is guaranteed that the invoked virtual is theone that is defined in the current object (or of the base class, if it has not been overridden in the current object) However,virtual member functions of objects that are derived from the one whose constructor is executing are not called Forexample

ANSI/ISO C++ Professional Programmer's Handbook - 4 - Special Mem nstructor, Copy Constructor, Destructor, And Assignment Operator

file:///D|/Cool Stuff/old/ftp/1/1/ch04/ch04.htm (3 von 24) [12.05.2000 14:46:07]

Trang 12

Please note that if the object's member functions refer to data members of the object, it is the 'programmer's

responsibility to initialize these data members first most preferably with a member-initialization list

(member-initialization lists are discussed next) For example

class Empty {}; //class has no base classes, virtual member functions

//or embedded objects

An implementation can instantiate Empty and Person objects without a constructor In such cases, the

explicitly-declared constructor is said to be trivial, which means that the implementation does not need it in order to

create an instance of its class A constructor is considered trivial when all the following hold true:

Its class has no virtual member functions and no virtual base classes

of size and speed as that which is produced by a C compiler

ANSI/ISO C++ Professional Programmer's Handbook - 4 - Special Mem nstructor, Copy Constructor, Destructor, And Assignment Operator

file:///D|/Cool Stuff/old/ftp/1/1/ch04/ch04.htm (4 von 24) [12.05.2000 14:46:07]

Trang 13

Avoid Reduplicating Identical Pieces Of Constructors' Code

It is very common to define a class that has more than one constructor For instance, a string class can define oneconstructor that takes const char * as an argument, another that takes an argument of type size_t to indicate theinitial capacity of the string, and a default constructor

is better to move the recurring code into a single nonpublic member function This function is called by every

constructor The results are shorter compilation time and easier future maintenance:

// the following function is called by every user-defined constructor

void init( size_t cap = DEFAULT_SIZE);

size_t size = strlen (s);

init(size + 1); //make room for null terminating character

length = size;

strcpy(pc, s);

ANSI/ISO C++ Professional Programmer's Handbook - 4 - Special Mem nstructor, Copy Constructor, Destructor, And Assignment Operator

file:///D|/Cool Stuff/old/ftp/1/1/ch04/ch04.htm (5 von 24) [12.05.2000 14:46:07]

Ngày đăng: 05/08/2014, 10:20