C + + System learning Seven: Classes

Source: Internet
Author: User
Tags class definition

The basic idea of a class is data abstraction and encapsulation.

Data abstraction is a programming technique that relies on interfaces and implements separation. The interface of a class includes the operations that the user can perform, and the implementation of the class includes the data members of the class, the function body responsible for the interface implementation, and the various private functions required to define the class.

Encapsulation implements the separation of the interface and implementation of the class. The encapsulated class hides its implementation details.

To implement data abstraction and encapsulation, a class needs to define an abstract data type first. In an abstract data type, the designer of the class takes care of the implementation of the class, which the user simply calls, without needing to know the type of work details.

1. Defining abstract data type definition member functions

The declaration of a member function must be inside a class, and its definition can be either inside the class or outside of the class. A function defined inside a class is an implicit inline function.

This

The member function accesses the object that invokes it by using an additional implicit parameter called this. When a member function is called, the This is initialized with the object address that requested the function.

TOTAL.ISBN ();

The compiler is responsible for passing the address of total to the implicit parameter this of ISBN.

Inside the member function, we can directly use the members of the object that called the function, without having to pass the member access operator.

String ISBN () const{        return this->bookno;}
Const member functions

By default, the type of this is a constant pointer to a very version of the class type. For example, in the Sales_data member function, the type of this is Sales_data *const. Although this is an implicit formal parameter to a member function, it still needs to follow the initialization rules, and we cannot bind this to a constant object. This also makes it impossible to invoke normal member functions on a constant object.

Therefore, in order to improve the flexibility of the function, we declare this as a pointer to a constant, and this is implicit in the parameter list of the member function, so we add a const to the argument list to indicate that this is a pointer to a constant. A const-decorated member function that is followed by a function is called a constant member function, and the content of the object that invokes it cannot be changed in a constant member function.

Note: Constant object, as well as a reference or pointer to a constant object, can only call a constant member function.

class scope and member functions

The compiler processes the class in two steps: the declaration of the member is compiled first, and then the member function is run. Therefore, the member function body is free to use other members of the class without worrying about the order in which they appear.

To define member functions outside of a class

When you define a member function outside a class, you must ensure that the return type, the argument list, and the function name are consistent with the declaration within the class, and that the const attribute must be explicitly specified after the argument list for the class declaration as a constant member function. At the same time, the name of the member defined outside the class must contain the class name to which it belongs.

1.3 Defining class-dependent non-member functions

Classes often need to define auxiliary functions, such as Read,print, although the operations defined by these functions are conceptually part of the interface of the class, but they do not actually belong to the class itself.

The definition of an auxiliary function usually separates the declaration and definition of the function. If a function is conceptually part of a class but not defined in a class, it should generally be within the same header file as the class declaration, not the definition.

1.4 Constructors

The task of the constructor is to initialize the data members of the class object and execute the constructor whenever the object of the class is created.

The constructor has the same name as the class name, no return type, and the others are the same as other functions. A class can contain multiple constructors, similar to other overloaded functions.

Constructors cannot be declared as const because their roles are both initialization class objects.

The default constructor for a composition

The class uses a special constructor to control the default initialization process, which is called the default constructor. The default constructor does not require any arguments.

If we do not explicitly define constructors, then the compiler implicitly defines a default constructor for us. If we explicitly define a constructor, the compiler will not generate a default constructor for the class, so you must define a default constructor yourself at this point.

Note: The compiler will automatically generate a default constructor only if the class does not declare any constructors.

Some classes cannot depend on the composition's default constructor

The default constructor for a composition is only suitable for very simple classes, and for a normal class, it must define its own default constructor.

    • You have defined some other constructors, you must define a default constructor
    • Classes that contain members of a built-in or composite type should initialize these members within the class, or define their own default constructors, or you might get undefined values when creating objects of the class. Because objects defined in blocks of built-in types or composite types are initialized by default, their values are undefined
    • Sometimes the compiler cannot synthesize default constructors for some classes
struct Sales_data{sales_data () = default; Sales_data (const string &s): Bookno (s) {}sales_data (const string &s, unsigned n, double p): Bookno (s), Units_sold ( N), Revenue (P*n) {}sales_data (IStream &); string ISBN () const{return Bookno;} sales_data& Combine (const sales_data&);d ouble avg_price () const;string bookno;unsigned units_sold = 0;double Revenue = 0.0;};
=default

You can ask the compiler to generate a constructor by writing a =default after the argument list. Where =default can be declared either in the interior of the class or as defined outside the class. If =default is inside a class, the default constructor is inline, and if outside of the class, the member is not inline by default.

Constructor initialization list
Sales_data (const string &s): Bookno (s) {}sales_data (const string &s, unsigned n, double p): Bookno (s), Units_sold ( N), Revenue (P*n) {}

The section between the colon and the curly braces is called the constructor initializer list. It is responsible for assigning an initial value to one or several data members of the newly created object. The constructor initial value is a list of member names followed by the initial values of the members enclosed in parentheses (or within curly braces). The initialization of different members is separated by commas.

When a data member is ignored by the constructor initializer list, it is implicitly initialized in the same way as the composite default constructor.

Note: Constructors should not easily overwrite the initial values within a class unless the newly assigned value differs from the original value. If you cannot use the initial value in the class, all constructors should explicitly initialize the members of each built-in type.

Defining a constructor 1.5 copy, assignment, and destructor outside the class

In addition to defining how objects of a class are initialized, classes need to control the behavior that occurs when copying, assigning, and destroying objects.

If we do not actively define these operations, the compiler will synthesize them for us. In general, the compiler-generated version performs copy, assignment, and destroy operations on each member of the object.

2. Access Control and encapsulation

In C + +, use the access specifier to enhance the encapsulation of classes:

    • Defines the interface of a public member to define a class that is accessible throughout the program, after the public specifier.
    • A member defined after the private specifier can be accessed by a member function of the class, but cannot be accessed using the class's code, and the private part encapsulates the implementation details of the class
Class and Struct keywords

The only difference is that the default access permissions are not the same, the default permissions for a struct are public, and the default permissions for class are private.

2.1 Friends

A class can allow other classes or functions to access its non-public members by making other classes or functions known as its friends.

If a class wants to use a function as its friend, it just needs to add a function declaration statement that starts with the friend keyword.

Classes can also define other classes as friends, or they can define member functions of other classes as friends.

A friend function can be defined inside a class, and such a function is implicitly inline.

Class sales_data{
        Friend Sales_data Add ();        Friend function
Public:sales_data () = default; Sales_data (const string &s): Bookno (s) {}sales_data (const string &s, unsigned n, double p): Bookno (s), Units_sold ( N), Revenue (P*n) {}sales_data (IStream &); string ISBN () const{return Bookno;} sales_data& Combine (const sales_data&);p rivate:double avg_price () const;string bookno;unsigned units_sold = 0; Double revenue = 0.0;};

Note: A friend declaration can only appear inside a class definition, but there is no limit to the exact location within the class. A friend is not a member of a class and is not constrained by the access control level of its area.

Friends are generally declared in a set of positions before the start or end of a class definition.

Friend Declaration

A friend's declaration specifies only the access permission, not a function declaration in the usual sense. If you want the user of a class to be able to invoke a friend function, you must declare the function in addition to the friend Declaration.

To make friends visible to the user of a class, it is common to place the declaration of the friend with the class itself in the same header file (outside of the class). Our Sales_data header file should provide separate declarations for read, print, and add (in addition to the friend declarations inside the class).

A friend relationship between classes

Some members of the window-managed class Window_mgr may need to access the internal data of the screen class that it manages, for example, the WINDOW_MGR member function clear needs to clean up the contents of one of the screens it manages. This time clear needs to be able to access the private members of screen, so you need to specify the Window_mgr class as its friend in the screen class.

Class screen{    friend class Window_mgr;};

If a class specifies a friend class, member functions of the friend class can access all members of the class, including non-public members. Therefore, the clear function of window_mgr can be defined as

void Window_mgr::clear (screen &s) {    s.content=string (s.height*s.width, '  );}

Above, the member function in Window_mgr clear can access the private data member of screen.

Note: The friend relationship does not have transitivity, and if the Window_mgr class has other friends, these friends do not have the privilege to access screen.

Each class is responsible for controlling its own friend or friend functions.

Make a member function a friend

In addition to the entire Window_mgr class as a friend, screen can provide access privileges only for clear.

When a member function is declared Chengyuan, it must be clearly indicated which class the member function belongs to;

Class screen{    friend void window_mgr::clear (screen &s);
function overloading and friend

If you want to declare one of several overloaded functions as friends, you can declare the function directly in the class, and only the function that is declared can access all the data members of the class.

Friend declarations and scopes

A friend's declaration is not a true declaration, and if it is to be used it must be added to the function declaration in its true meaning.

3. Other properties of Class 3.1 class members define a type member

In addition to defining data and function members, a class can also customize aliases for a type in a class. The type name defined by the class has access restrictions like other members, which can be one of public or private.

Class screen{public:using pos = Std::string::size_type;private:pos curser = 0;pos height = 0, width = 0;std::string conten t;};

Note: Type members usually appear where the class begins.

member functions for the screen class
Class screen{public:using pos = Std::string::size_type; Screen () = default;//because screen has another constructor,//So this function is required screen (POS HT, POS wd, char C): Height (HT), Width (wd), Content (HT*WD, c) {}char get () Const{return content[cursor];} inline char get (POS HT, POS wd) const; Screen &move (POS R, pos c);p rivate:pos curser = 0;pos height = 0, width = 0;std::string content;};
Make a member an inline function

The member functions defined inside the class are automatically inline, and the constructors and get functions for screen above are the inline functions by default.

You can explicitly declare member functions inside a class as part of a declaration, as well as by using the inline keyword to modify the definition of a function outside the class.

#include "2.h" Inlinechar Screen::get (POS R, pos c) const{pos row = R*width;return Content[row + c];}

While it is not necessary to explain inline at the same time as it is declared and defined, it is lawful to do so. However, it is best to explain inline only where it is defined outside the class, which makes the class easier to understand.

Overloaded member functions

member functions can also be overloaded.

Variable data members

Sometimes you want to be able to modify a data member of a class, even within a const member function, by adding the mutable keyword to the declaration of the variable.

A mutable data member is never a const, even if it is a member of a const object. Therefore, a const member function can change the value of a mutable member. For example, you can add a variable member to screen to record the number of times a member function is called.

Private:pos curser = 0;pos height = 0, Width = 0;std::string content;mutable size_t access_cnt;=========================== = #include "2.h" Inlinechar Screen::get (POS R, pos c) const{++access_cnt;pos row = R*width;return Content[row + c];}
The initial value of the class data member

The initial value in the class must use the initialization form of = or the direct initialization form enclosed in curly braces.

3.2 Returning the member function of *this

Return *this You can embed functions into a set of action sequences.

Myscreen.move (4,0). Set (' # ');
Returning *this from the const member function

A const member function if the *this is returned as a reference, its return type will be a constant reference and cannot be embedded in a set of action sequences.

Const-based overloading

For overloads of a const member function and a constant member function, decide which member function to call, depending on whether the object is a literal.

3.3 Class Type

Each class defines a unique type. For two classes, even though their members are exactly the same, these two classes are two different types.

Declaration of the class

It can only be declared and not defined for the time being. Such a declaration is referred to as a forward declaration. For a class, however, the class must be defined before the object is created, not just declared, because the compiler needs to know how much storage space the object of the class requires.

4. Scope scope of the class and members defined outside the class

Once the class name is encountered, the remainder of the definition is within the scope of the class, where the remainder includes the argument list and the function body. Saved is that you can use the other members of the class directly without having to authorize again.

void Window_mgr::clear (Screenindex i) {screen    &s=screens[i];    S.contents=string (S.height*s.width, ');}

The above window_mgr:: It has been clearly stated that the following sections are in the Window_mgr scope, so the WINDOW_MGR members Screenindex and screens do not need to explain the scope of window_mgr, However, in Window_mgr: The function return type portion before the scope is not in the window_mgr scope, so if the function return type part needs to use a member in Window_mgr, the member must be namespace-descriptive.

Assuming that the return type is screenindex, the definition outside the class should be window_mgr::screen_mgrwindow_mgr::clear (Screenindex i) {}
4.1 Name lookup and scope of the class

In general, the steps for name lookup are as follows:

    • Look for its declaration statement in the block where the name resides, considering only the declaration that appears before the name is used
    • If not found, continue looking for the outer scope
    • If a matching claim is not found, the program error

However, for member functions inside a class, the procedure for name lookup is different, and the definition of the class is handled in two steps:

    • First, the declaration of the compiled member
    • The function body is not compiled until the class is all visible

Note: The definition of a member function is not processed until the compiler finishes processing all declarations in the class.

Name lookup for class member declarations

The above two-stage processing applies only to names used in member functions. The name used in the declaration, including the return type or name used in the parameter list, must be visible before use.

Type name to be handled specially

The definition of a type name usually appears at the beginning of the class, ensuring that all members that use that type appear after the definition of the class name.

typedef double Money;class screen{};
Name lookup for a normal block scope in a member definition

The names used in the member functions are parsed as follows:

    • First, find the declaration of that name within the member function
    • If it is not found within the member function, continue searching within the class
    • If no declaration of that name is found within the class, the lookup continues in the perimeter scope

When a member function declares a member with the same name as a member of a class, the declaration in the member function overrides a member of the same name in the class, and if you want to use a member of the same name as the class, you can either add the name of the class or explicitly use the this pointer to force access to the members of the class.

5. Further discussion of Constructor 5.1 constructor initializer list
Sales_data::sales_data (const string &s, unsigned cnt, double price) {    bookno=s;    units_sold=cnt;    Revenue=cnt*price;}

Note that this constructor is written in a different form than using a colon, except that the colon is used to initialize its data member, and this version performs an assignment on the data member. This is based on the type of data member that will have a deep impact on the exact difference.

The initial value of the constructor is sometimes necessary

Sometimes it is possible to ignore the differences between the initialization and assignment of data members, but this is not always the case. If a member is const or a reference, it must be initialized. Similarly, this member must be initialized when the member is of a certain type and the class does not have a default constructor defined.

Class Constref{public:    constref (int ii);P rivate:    int i;    const int CI;    int &ri;}; Constref::constref (int ii) {    i=ii;    Correct    ci=ii;    Error, cannot assign value ri=i to const    ;    Error, RI not initialized}
The correct constructor should be
Cosntref::constref (int II): I (ii), CI (ii), RI (i) {}

Note: If a member is a const, a reference, or a class type that does not provide a default constructor, we must provide the initial value for those members through the constructor initializer.

We recommend that you use the constructor initial value.

The order in which member initialization is initiated

The initialization order of members is consistent with the order in which they appear in the class definition, and the pre-and post-position relationships of the initial values in the constructor's initializer list do not affect the actual initialization order.

Note: It is best to keep the order of the constructor's initial values consistent with the order of the member declarations and, if possible, to avoid using some members to initialize other members.

Default arguments and constructors

If a constructor provides default arguments for all parameters, it actually defines the default constructor as well.

5.2 Delegate Constructors

A delegate constructor performs its own initialization process using the other constructors of the class it belongs to, or it delegates some of its own responsibilities to other constructors.

Class Sales_data{public:    sales_data (String s,unsigned cnt, double price): Bookno (s), Units_sold (CNT), Revenue (cnt* Price) {}    //The rest of the constructors are all delegated to the above constructor    Sales_data (): Sales ("", 0,0) {}    Sales_data (string s): Sales_data (s,0,0) {}    Sales_data (IStream &is): Sales_data () {read (is,*this);}};

When a constructor is delegated to another constructor, the list of initial values of the constructor of the delegate and the body of the function are executed sequentially. In the Sales_data class, the constructor body of the delegate is exactly empty. Adding a function body containing code will execute the code first and then the control will be handed back to the delegate's function body.

5.3 Function of the default constructor

In practice, if you define other constructors, it is best to also provide a default constructor

5.4 Implicit class-type conversions

You can define an implicit conversion rule for a class.

If a constructor accepts only one argument, it actually defines an implicit conversion mechanism that is converted to such a type, sometimes referred to as a conversion constructor.

Only one-step class type conversions are allowed

The compiler will only perform one-step type conversions automatically

Item.combine ("hello!");

This is wrong and requires two kinds of conversions, first of all "hello!" Convert to a string, and then convert the temporary string to Sales_data.

For this type of error, you can explicitly "hello!" Convert to String

Item.combine (String ("hello!"))
Class type conversion is not an implicit conversion of the total effective suppression constructor definition

You can block the implicit conversion of a constructor by declaring the constructor as explicit

Class Sales_data{public:    sales_data () =default;    Sales_data (const string &s,unsigned n,double P): Bookno (s), Units_sold (n), Revenue (P*n) {}    explicit Sales_data ( Const string &s): Bookno (s) {}    explicit Sales_data (istream&);};

At this point, no constructor can be used to implicitly create the Sales_data object.

Item.combine (Null_book); Item.combine (CIN);

Neither of these attempts to convert through string and IStream to Sales_data objects can be compiled.

Note:explicit is only valid for constructors of one argument, and the explicit keyword is used only when the constructor is declared within a class, and should not be duplicated when defined outside the class.

The explicit constructor can only be used for direct initialization
Sales_data item1 (null_book);    correctly, the Sales_data item2=null_book;//error is initialized directly, and the Null_book wants to be implicitly converted to Sales_data, but the constructor declares explicit and therefore cannot be implicitly converted
Explicitly using constructors for transformations

Although the compiler does not use the explicit constructor for implicit conversions, you can use such constructors for explicit casts.

Itme.combine (Sales_data (Null_book));    Call the Sales_data constructor directly item.combine (Static_cast<sales_data> (CIN));    Forced conversions
5.5 Aggregation Classes

The aggregation class gives users direct access to their members and has a special initialization syntax form. When a class satisfies the following conditions, it is an aggregation class

    • All members are public
    • No constructors are defined
    • No intra-class initial values
    • There is no base class, and there is no virtual function

You can provide a list of member initial values enclosed in braces and use it to initialize the data members of the aggregation class. The order of the initial values must be the same as the order in which they are declared, and if the number of initial values is less than the number of members of the class, then the default is initialized.

6. Static members of a class

A static member of a class is related only to the class itself, regardless of the object of the class.

declaring static members

Precede the declaration with the "static" keyword so that it is associated with the class. As with other members, a static member can be public or private.

Static member functions are also not bound to any objects, and they do not contain the this pointer. Static member functions cannot be declared as const, and the This pointer cannot be used within the static function body.

Using static members of a class

Use the scope operator to access static members directly.

Double R;r=account::rate ();

You can also use the object, reference, or pointer of a class to access static members.

Account AC1; Account *ac2=&ac1;r=ac1.rate (); R=ac2->rate ();

member functions can use static members directly without using the scope operator.

Defining static Members

You can define static member functions within a class or outside of a class. When static members are defined outside the class, the static keyword cannot be repeated, and the static keyword can only appear within the declaration statement inside the class.

In general, static members cannot be initialized inside a class. Instead, each static member must be defined and initialized outside of the class, and can only be defined once.

1.hclass account{private:    static double interestrate;    Static double Initrate ();}; 1.cppdouble account::interestrate=initrate ();    Defining and initializing static members

Starting with the class name account, the remainder of the definition statement is within the scope of the class, so you can use the Initrate function directly, even if it is private.

In-class initialization of static members

Even if a constant static data member is initialized inside a class, it is often a rule to define the member outside of the class.

Static members can be used in certain scenarios, while ordinary members cannot

The type of a static data member can be the class type to which it belongs, while non-static data members are restricted and can only be declared as a pointer or reference to the class to which it belongs.

Class Bar{private:    static Bar mem1;    Correctly, a static member can be an incomplete type    Bar *mem2;            Correctly, a pointer member can be an incomplete type    Bar  mem3;            Error, the data member must be of the full type};

Another difference between a static member and a normal member is that you can use a static member as the default argument

Class Screen{public:    screen&  Clear (char=bkground);p rivate:    static const char bkground;};

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.