C + + Primer Learning notes _104_ special tools and techniques--Nested classes

Source: Internet
Author: User

Special tools and techniques--Nested classes

You can define a class inside another class (unlike the local class described later , in which a nested class is inside a class ) , such that a class is a nested class, also known as a nested type. Nested classes are most commonly used to define execution classes.

Nested classes are independent classes and are basically unrelated to their perimeter classes, so the objects of the perimeter class and the nested class are independent of each other. Objects of a nested type do not have members defined by a perimeter class, and members of a perimeter class do not have members defined by a nested class.

The name of a nested class is visible in the scope of its perimeter class, but not in the scope of another class scope or defined perimeter class. The name of a nested class will not conflict with a name declared in another scope

Nested classes can have members of the same kind as non-nested classes. Like any other class, a nested class uses an Access label to control access to its members. Members can be declared as public,private , or protected. The perimeter class has no special access to the members of the nested class, and the nested class has no special access to the members of its perimeter class .

a nested class defines a type member in its perimeter class. Like any other member, the perimeter class determines access to this type.

Implementation of nested classes

Instance

WillQueueitemclass is set toQueueClass ofPrivatemembers, then,Queueclass (and its friends) can use theQueueitem, butQueueitemclass types are not visible to normal user code. OnceQueueitemclass itself isPrivate, we can make its members Publicmember--onlyQueueorQueuefriends can access theQueueitemtype, so you do not have to prevent general program AccessQueueitemmembers. By using reserved wordsstructdefinitionQueueitemmake a member Publicmembers.

The new design is as follows:

Template <typename type>class queue{public:    //...private:    struct queueitem    {        Queueitem (const Type &);        Type item;        Queueitem *next;    };    Queueitem *head;    Queueitem *tail;};

1. A class nested inside a class template is a template

because queue so its members are also templates , and queueitem queue template parameters are the same

each instantiation of the Queue class produces its own Queueitem class with the appropriate template argument corresponding to Type . The mapping between the instantiation of the Queueitem class template and the instantiation of the perimeter Queue class template is one-to-one .

2. Defining members of nested classes

Nested class members that are defined outside their class must be defined in the same scope that defines the perimeter class . A member of a nested class defined outside its class cannot be defined inside a perimeter class, and members of a nested class are not members of a perimeter class .

the constructor of the Queueitem class is not a member of the queue class, so it cannot be defined anywhere in the queue class definition body .

Template <class Type>queue<type>::queueitem::queueitem (const Type &t): item (t), next (0) {}

Because Queue and queueitem are templates , This constructor is also a template .

3. Defining nested classes outside the perimeter class

Nested classes typically support the implementation details of the perimeter class. We may want to prevent users of the perimeter class from seeing the implementation code for the nested class.

For example, we might want to place the definition of the queueitem class in its own file, which we can include in the implementation file for the Queue class and its members. Just as members of a nested class can be defined outside the class definition body, we can also define the entire nested class outside the perimeter class definition body:

Template <typename type>class queue{public:    //...private:    struct queueitem;    Queueitem *head;    Queueitem *tail;}; Template <class type>struct queue<type>::queueitem{    queueitem (const Type &t): item (t), next (0) {}    Type Item;    Queueitem *next;};

Note that we have to declare the queueitem class inside the Queue class body .

[ caution ]

Before you see the actual definition of a nested class defined outside the class definition body, the class is an incomplete type , applying all the general restrictions that use the incomplete type.

4. Nested class static member definitions

If the queueitem class declares a static member , Its definition also needs to be placed in the outer scope , assuming that the Queueitem There is a static member :

Template <class Type>int queue<type>::queueitem::static_mem = 1024;

5. Using members of the perimeter class

There is no connection between an object of a perimeter scope and an object of its nested type

Template <typename type>void Queue<type>::p op () {    Queueitem *q = head;    Head = head Next;    Delete q;}

an object of type Queue does not have a name of item or next member . Queue a function member of a class can use the Head and the Tail members (they are points to Queueitem object) to get those Queueitem members.

6. Using static members or other types of members

A nested class can directly reference a static member of a perimeter class, a type name , and an enumeration member [ with the local class described later ]. however , References A type name or static member outside the scope of a perimeter class requires a scope determination operator .

7. Instantiation of nested templates

nested classes of class templates are not automatically instantiated when you instantiate a perimeter class template. As with any member function, nested classes are instantiated only when the nested class itself is used in cases where the full class type is required . For example, like



Such a definition, the Queue template is instantiated with an int type , but the queueitem<int> type is not instantiated . members head and tail are pointers to queueitem<int>, which do not need to be instantiated queueitem<int> to define a pointer to that class.

Only when using queueitem<int> - - only if the member function of the queue<int> class the queueitem<int> class is instantiated only when head and tail are dereferenced .

Name lookup in nested class scopes

When processing a class member declaration , the name used must appear before use ; when processing When defined , the entire nested class and the perimeter class are in scope .

Class Outer{public:    struct Inner    {        void process (const Outer &);    OK        Inner2 val;     Error    };    struct Inner2    {public    :        Inner2 (int i = 0): Val (i) {}        void process (const Outer &out)  //ok< c23/>{            Out.handle ();        }    Private:        int val;    };    void handle () const;};

[ description ]

compiler first handles  OUTER&NBSP, and   . The name  OUTER&NBSP; as   inner::p rocess  PROCESS&NBSP; that class is still incomplete, but , So this use is correct.  

The declaration of the data member Inner::val is wrong, and the Inner2 type has not been seen.

the declarations in Inner2 seem to have no problem -they mostly only use built-in type int. The only exception is the member function process, whose formal parameters are determined to be of the incomplete type Outer. Because its formal parameter is a reference, it does not matter if the Outer is an incomplete type.

The compiler handles the definition of constructors and process members until you see the rest of the declarations in the perimeter class . The completion of the Outer class declaration places the declaration of the function handle in scope.

When the compiler looks forInner2class, the name of the definition used in theInner2Classes andOuterall names in the class are in scope. the use of Val (before the declaration of Val ) is correct: Bind the reference to a data member in the Inner2 class[I don't understand what this paragraph means .%>_<%]。 SameInner2::p rocessin the member function bodyOuterClass ofHandleAre also used correctly,when compiling members of the Inner2 class, the entire Outer class is in scope。

Using scope operators to control name lookups

You can use the scope operator to access the global version of handle :

        void process (const Outer &out)        {            :: Hadle (out);        }

Related Article

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.