C ++ (3)

Source: Internet
Author: User

Clause 26 operator function search

Class X

{

Public:

Xoperator % (const X &) const; // binary remainder operation

XmemFunc1 (const X &);

VoidmemFunc2 ();

};

You can use the infix or function call syntax to call this overload OPERATOR:

X a, B, c;

A = B % c; // use the infix syntax to call the member operator %

A = B. operator % (c); // member function call syntax

A = B. memFunc1 (c); // call another member function

However, the processing mechanism for infix calls in many love operators is different from this:

X operaator % (const X &, int); // non-member operator Declaration

//...

Void X: memFunc2 ()

{

* This % 12; // call the non-member operator %

Operator % (* this, 12); // error! Too many arguments

}

The first infix call to operator % will match the one that is not a member. This is not an example of overloading, but the compiler looks for candidate functions in two different places. The second non-infix call to operator % allows the standard function search rule to match the member function, but here we will encounter an error, because we try to pass three arguments to a binary function. (Remember, the call to a member function has an implicit real parameter this !)

Article 27 capability Query

Capability query is usually expressed by converting irrelevant types into dynamic_cast.

Class Shape {

};

Class Rollable {

};

Class Square: public Shape {

};

Class Wheel: public Rollable, publicRollable {

};

Shape * s = getSomeShape ();

Rollable * roroller = dynamic_cast (S );

This kind of dynamic_cast usage is often called a much like transformation, because it views perform horizontal conversions in the result of a class. If s refers to an object with a Square, dynamic_cast will fail, so that the Shape s points to is not a Rollable. If s points to a Circle or other shapes derived from Rollable, the transformation will succeed.

Article 28 meanings of pointer comparison

In C ++, an object can have multiple valid addresses. Therefore, pointers are not address problems, but object identity problems. See the following example.

#include 
 
   class Shape{public:    int a;};class Subject{public:    int b;};class ObservedBlob : public Shape,public Subject{};int main(){    ObservedBlob* ob = newObservedBlob();    Shape* s = ob;    Subject* subj = ob;    void* v =subj;    printf("%d\n",ob);    printf("%d\n",s);    printf("%d\n",subj);     if(subj ==ob)       printf("subj= ob\n");    else       printf("subj!= ob\n");     if(subj == v)       printf("subj= v\n");    else       printf("subj!= v\n");     if(ob == v )       printf("ob= v\n");    else       printf("ob!= v\n");     return 0;}
 


The running result is as follows:

3759208

3759208

3759212

Subj = ob

Subj = v

Ob! = V

Press any key to continue...

Since ob, s, and subj all point to the same object, the compiler must distinguish between ob and s and subj to true. The compiler adjusts a certain offset from one of the points in the comparison to complete the comparison. For example, expression:

Ob = subj;

May be translated

Ob? (Ob + delta = ubj): (subj = 0)

Therefore, the result in this example is ob = subj.

However, when we handle pointer or reference to an object, we must be careful not to lose type information. A pointer to void is a common error. As shown above, copying the object pointer to void * removes the address type information contained in the object. The compiler has no choice but to compare the original address. So the above results will appear.
Subj = v

Ob! = V

Clause 29 virtual constructor and Prototype mode

When ordering a meal, you can use the following procedure to order a food that someone else eats:

Class Meal {public: virtual ~ Meal (); virtual voideat () = 0; virtual Meal * clone () const = 0 ;//...}; Class Spaghetti: publicMeal {public: Spaghetti (const Spaghetti &); // copy the constructor voideat (); Spaghetti * clone () const {return new Spaghetti (* this ); // call the copy constructor }}; constMeal * m = thatGuyMeal (); // whatever Meal * myMeal = m-> clone () He is eating (); // I want the same copy as him!


In fact, it is entirely possible that we do not know much about the transaction.

The Prototype mode is actually used here. The existence of a type does not cause any obstacle to the creation of objects of this type.

The so-called virtual constructor is not a real virtual constructor, but a copy of the generated Object usually involves indirect calls to the constructor of its class by a virtual function, it is also a virtual constructor.

Clause 30 Factory Method mode

The essence of Factory Method is that the base class provides a virtual function hook to generate appropriate products. Each derived class can override the inherited virtual function to generate an appropriate product for itself. In fact, we have the ability to use a location type object to generate another unknown type object.

Clause 31 covariant return type

In general, a function to be rewritten must have the same return type as the function to be rewritten.

However, this rule is not strict with "return type of covariant. That is to say, if B is a class type and a base class virtual function returns B *, then a rewritten derived class function can return D *, where D is derived from B. If the base class virtual function returns B &, then a rewritten derived class function can return a D &.

Cla32 copying prohibited

You can declare the copy operation (copy constructor and copy value assignment function) as private without providing definition.

Cla33: Manufacturing abstract base

Abstract base classes are used to abstract concepts in the target question field. It makes no sense to create a favorite class of this type. We declare at least one pure virtual function to make a base class abstract. the compiler will ensure that no one can create any object of this abstract base class. For example:

Class ABC {

Public:

Virtual ~ ABC ();

Virtual void anOperation () = 0; // pure virtual function

};

However, sometimes you cannot find a reasonable candidate for pure virtual functions, but you still want the class to behave like an abstract class. It can be implemented using the following methods.

Method 1: You can simulate the properties of the abstract base class by ensuring that there is no public constructor in the class. We need to explicitly declare the default constructor and the copy constructor, and the two constructor should be protected to allow the constructor of the derived class to use them, it also blocks the creation of independent ABC objects.

Class ABC

{

Public:

Virtual ~ ABC ();

Protected:

ABC ();

ABC (const ABC &);

};

Class D: publicABC

{

//...

};

Void func1 (ABC );

Void func2 (ABC &);

ABC a; // error! The default constructor is protected.

D d; // OK

Func1 (d); // error! The replication constructor is protected,

Func2 (d); // OK, does not involve the replication Constructor

Method 2: another way to make a class an abstract base class is to specify a virtual function of the class as a pure virtual function. Usually, destructor are a good choice:

Class ABC {

Public:

Virtual ~ ABC () = 0;

};

ABC ::~ ABC (){...}

Note: In this example, it is necessary to provide an implementation for the pure virtual function, because the destructor of the derived class will call the destructor of its base class implicitly (note, an implicit call to a base class Destructor from a derived class is always non-virtual ).
Method 3: protected destructor and protected constructor play basically the same effect. However, the error of the former occurs when the object is out of scope or is displayed as destroyed, instead of when the object is created.

Class ABC {

Protected:

~ ABC ();

Public:

//...

};

Void someFunc ()

{

ABC a; // No error is reported at this time

ABC * P = new ABC; // No error is reported at this time

Delete p; // error! Protected during destructor

// Error! Call the destructor of a implicitly

}

Cla34 prohibit or force the use of heap allocation

Sometimes it is a good idea to specify that objects of certain classes should not be allocated to the stack. This is usually used to ensure that the destructor of the object is called. The handle object that maintains the reference count of the ontology object belongs to this object. For local objects with classes in the automatic storage area, the Destructor is called, and objects with classes in the static storage area are also called.

One of the methods to specify that an object should not be allocated to the stack is to define its memory allocation as illegal:

Class NoHeap

{

Public:

//....

Protected:

Void * operator new (size_t) {return 0 ;}

Void operator delete (void *){}

};

Any habitual attempt to allocate a NoHeap object on the stack will produce a compiler error.

NoHeap * nh = new NoHeap; // error! NoHeap: operatornew is protected

//...

Delete nh; // error! NoHeap: operatordelete is protected

Operator new and operator definitions are given because they may be called by constructor and destructor on some platforms. For the same reason, we declare them as protected because they may be implicitly called by the constructor and destructor of the derived class. If NoHeap is not intended to be used as a base class, the two functions can also be declared as private.

At the same time, be sure to prevent the stack from allocating arrays of NoHeap objects. In this case, you only need to declare array new and array delete as private and do not define them. This is similar to the method of prohibiting copy operations.

Class NoHeap {

Public:

//...

Protected:

Void * operator new (size_t) {return 0 ;}

Void operatoe delete (void *){}

Private:

Void * operator new [] (size_t );

Void operator delete [] (void *);

};

Of course, in some cases, we may encourage the use of pair allocation, just declare the Destructor as private.

Class OnHeap {

~ OnHeap ();

Public:

Void destroy ()

{

Delete this;

}

};

When an object name leaves its scope, any attempt to declare an automatic or static OnHeap object will generate an implicit destructor call:

OnHeap oh1; // error! Call Private destructor implicitly

Void aFunc ()

{

OnHeap oh2;

//...

// Error! Call the oh2 destructor implicitly

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.