Valid tive C ++ 55 01-12 notes

Source: Internet
Author: User
Tags constant definition

Clause 01: regard C ++ as a Language Federation: C, object-oriented C ++, template C ++, STL

Clause 02: replace const, Enum, and inline whenever possible # define:

1. For simple constants, it is best to replace it with a const object or enum # define

2. For macro (macros) Like a function, it is best to replace it with the inline function # define

# Define aspect_ratio 1.653

Constdouble aspectratio = 1.653;

1) The name defined by # define may not be entered into the mark table, and compilation error may be inconvenient for tracking.

2) using const to define constants will produce a more streamlined goalCode(Object Code), because Preprocessor processing # define will blindly Replace the macro name with 1.653, resulting in more than 1.653 copies of the target code. If you use const, this problem will not occur.

When you replace # define with constants, there are two special cases.

1) define a constant pointer. Since the constant definition is usually placed in the header file (so that it can be included in different source code), it is necessary to declare the pointer As Const.

Const char * const authorname = "Scott Meyer ";

String objects are generally better than char *-base, so authorname is often defined as const STD: String authorname ("Scott Meyer ");

2) Class exclusive constants. To limit the scope of a constant to a class and ensure that the constant has at most one entity, you must make it a static member:

Class gameplayer {

PRIVATE:

Static const int numturns = 5;

Int scores [numturns];

...

}

Generally, members of the static & const & Integer type (ints, chars, bools) can be declared and used without the need to define the address. However, if you take the address of an exclusive constant of a class, or your Compiler (incorrectly) insists that the following definition must be provided to see a definition

Const int gameplayer: numturns; // Put It In The implementation file. Because the initial value has been obtained during declaration, the initial value cannot be set.

We cannot use # define to create class-specific constants, because # define does not pay attention to scope.

In old times, the compiler may not support the above syntax and does not allow static members to provide initial values during declaration.

The initial value is put into the definition, but the compiler insists that the score [] size of the array must be known during compilation. in case your compiler does not allow the static integer class constant to complete the in class Initial Value Setting, you can use the enum hack compensation method instead.

Class gameplayer {

PRIVATE:

Enum {numturns = 5 };

Int scores [numturns];

}

1) it is invalid because Enum is the same as the # Define address. If you don't want others to get a pointer or reference pointing to an integer constant, Enum can help you implement this constraint. Like # defines, enums does not cause unnecessary memory allocation.

2) Practical, a lot of code is used. Enum hack is the basic technology of template metaprogramming.

Another common # define misuse is to use it to implement macros. Macros look like functions, but they do not incur additional overhead from function calls.

# Define max (a, B) f (a)> (B )? (A) (B ))
Int A = 5, B = 0;
Max (++ a, B); // A is accumulated twice
Max (++ A, B + 10); // A is accumulated once

Replace with Inline template functions: Macro efficiency and type security, predictable behavior
Template <typename T>
Inline void max (const T & A, const T & B)
{
F (A> B? A: B );
}

Cla03: Use const as much as possible

Const rational operator * (const rational & LHS, const rational & RHs); // Why do I return a const object?

Rational A, B, C;

...

(A * B) = C ;//

If (A * B = c )... // In fact, const can be returned to prevent such problems.

Const member function: can be called by a const object. If the two functions have different constants, they can be overloaded.

You can use mutable to release the bitwise constness constraint of the non-static member variable (that is, the member variable modified by mutable can be modified by the const member function ).

Avoid repetition in const and non-const member functions:

Class textblock {

Public :...

Const char & operator [] (STD: size_t position) const {

...

Return text [position];

}

Char & operator [] (STD: size_t position) {// The non-const member function calls the const member function to avoid code duplication.

Return

Const_cast <char &> (

Static_cast <const textblock &> (* This)

[Position]);

}

PRIVATE: STD: String text ';

};

Const member functions cannot call non-const member functions, and objects may be modified.

Clause 04: objects are initialized before they are used.

1. Manual initialization of built-in types

2. It is best for constructors to use the member Initial Value column member initialization list instead of assigning values in the constructor. The order of member variables listed in the initial value column must be consistent with the declared order in the class.

3. To avoid the issue of the initialization order of cross-compilation units, replace the non-local static object with the local static object.

Class {

Public: A (const string &);

PRIVATE:

String STR;

Int num;

}

A: A (const string & S ){

STR = s; // assign values instead of initialization. One default constructor is called in the initial value column, and one value assignment operation in the function body.

Num = 0'; // the built-in type is not guaranteed.

}

C ++ specifies that the initialization of the object's member variables takes place before the constructor body. If the member variable is a const or a reference, you must initialize the variable without being assigned a value.

A: A (const string & S): STR (s), // The value calls the copy constructor once.

Num (0 ){}

Static object: from being constructedProgramEnd. Main () automatically analyzes the structure at the end.

Including global objects, objects in namespace, objects declared as static in class, function, and file scope.

Local static object: static object in the function

Non-local static object: Other

If the initialization action of a non-local static object in a compilation unit uses a non-local static object in another compilation unit, the object may not be initialized. C ++ does not explicitly define the initialization sequence of the non-local static object defined in different units.

Class filesystem {

Public :...

STD: size_t numdisks () const;

};

Extern filesystem TFs;

// Another compilation unit

Class directory {

Public:

Directory (Params );

};

Directory: Directory (Params ){

STD: size_t disks = TFs. numdisks ();

}

Directory tempdir (Params );

Solution: in singleton mode, replace the non-local static object with the local static object.

C ++ ensures that the local static object in the function will be initialized when the function is called for the first time when the object definition is met.

Class filesystem {...};

Filesystem & TFS (){

Static filesystem FS;

Return FS ;}

Class directory {...};

Directory: Directory (Params ){

STD: size_t disks = TFS (). numdisks ();

};

Directory & tempdir (){

Static directory TD;

Return TD ;}

Article 05: understand which functions are compiled and called in C ++

The compiler secretly creates default constructor, copy constructor, copy assignment operator, and destructor for the class.

The compiler automatically generates a default constructor only when no constructor is defined for a class.

If no replication constructor is defined, the compiler combines one, even if other constructor is defined.

Template <class T>

Class namedobject {

Public: namedobject (string & name, const T & Value): namevalue (name), objectvalue (value ){}

PRIVATE: string & namevalue;

Const t objectvalue;

};

String newdog ("AAA ");

String olddod ("BBB ");

Namedobject <int> P (newdog, 2 );

Namedobject <int> S (olddog, 36 );

P = s; // compilation failed

The value assignment operator is supported in the class containing references or const members. You must define the copy assignment operator yourself (not the value assignment in the copy constructor ).

If a base class declares the copy assignment operator as private, the compiler rejects generating a copy assignment operator for Its Derived classes.

Clause 06: if you do not want to use a function automatically generated by the compiler, you should explicitly reject it.

Solution: declare the corresponding member functions as private and do not implement them. Or use base class like uncopyable

Explicitly declare a member function to prevent the compiler from generating the function, and use the other function as private to prevent external calls.

However, member functions and friend functions can still be called in reverse order, so they are declared without being defined. If they are called accidentally, a connection error is returned.

Move the connection period error to the compiler:

Class uncopyable {

Protected: uncopyable () {}// allow derived Object Construction and Structure

~ Uncopyablel (){}

PRIVATE: uncopyable (const uncopyable &); // But copying is blocked

Uncopyable & operator = (const uncopyable &);

};

Class homeforsale: Private uncopyable {...};

When you try to copy the homeforsale object, the copy constructor and copy assignment operator are automatically generated, and the base class version is called, but the operation fails...

Cla07: declare virtual destructor for a polymorphism base class

1. If the class has any virtual function, it should have a virtual destructor.

2. The purpose of the class is not to be used as a base class or to have polymorphism. It is not declared as a virtual destructor.

C ++ explicitly states that when the derived object is deleted by the base class pointer and the base class carries a non-virtual destructor, the result is undefined: Local destruction.

Each
A class with virtual functions has an array vtbl (virtual table) consisting of function pointers ).
When an object calls a virtual function, the actually called function depends on the vptr (virtual table
Pointer) refers to the vtbl in which the compiler looks for the appropriate function pointer. If the Destructor is declared as virtual without reason, it will increase the space compensation for the vptr.

Class specialstring: public STD: String {// unknown!

};

Specialstring * PSS = new specialstring ("AAA ");

STD: string * PS = PSS;

Delete pS; // undefined!

If you attempt to inherit a standard container or any other class with non-virtual destructor, reject the temptation !!!

Declare a pure virtual destructor for the class you want to become abstract (not materialized)

Class awov {

Public: Virtual ~ Awov () = 0;

};

A definition of awov: awov () {} must be provided (){}

Otherwise, the connector reports an error when the derived class destructor calls the base class destructor.

Cla08: do not escape exceptions from destructor

1. Do not spit out exceptions in destructor. If a function called by the Destructor may highlight an exception, the Destructor should capture any exception and swallow (not spread) or terminate the program.

2. If the customer needs to respond to exceptions thrown during the running of an operation function, the class should provide a common function (rather than the destructor) to execute this operation.

When the stack is expanded, the memory used by the local object is released and the destructor of the local object of the class type are run. If an exception already exists before executing the destructor, another exception is thrown in the destructor, which will cause the standard library to be called.TerminateThe function forces the program to exit abnormally.

Class dbconnection {

Public: static dbconnection create ();

Void close ();

};

Make sure that dbconnection does not forget to call close ()

Class dbconn {

Public:

~ Dbconn (){

DB. Close ();}

PRIVATE: dbconnection dB;

};

Dbconn DBC (dbconnection: Create ());

If the Destructor throws an exception:

1) force end

Dbconn ::~ Dbconn (){

Try {dB. Close ();}

Catch (...) {

Make a running record and write down the call to close failed.

STD: Abort ();

}

2) swallowed exception

Dbconn ::~ Dbconn (){

Try {dB. Close ();}

Catch (...) {

Make a running record and write down the call to close failed.

}

3) for better policies, the customer calls common functions by themselves

Class dbconn {

Public:

Void close (){

DB. Close ();

Closed = true;

}

~ Dbconn (){

If (! Closed ){

Try {dB. Close ();}

Catch (...) {

Make a running record and write down the call to close failed.

Abort or swallow exception

}

}

PRIVATE: dbconnection dB;

Bool closed;

};

Clause 10: Make operator = return a reference to * This

Clause 11: handle self-assignment in operator =

Class bitmap {...};

Class widget {

PRIVATE: bitmap * pb;

};

Widget & Widget: Operator = (const widget & RHs ){

Delete Pb; // No self-assignment detection is performed

PB = new Bitmap (* RHS. Pb); // No security exception occurs. When an exception occurs, Pb points to a deleted memory.

Return * this;

}

Solution: Same Test

Widget & Widget: Operator = (const widget & RHs) {// no exception Security

If (this = & RHs) return * this;

Delete Pb;

PB = new Bitmap (* RHS. Pb); // no exception Security

Return * this;

}

Widget & Widget: Operator = (const widget & RHs ){

Bitmap * porig = Pb; // exception security, and can handle self-assignment. When the frequency of Self-assignment is high, you can add the same test.

PB = new Bitmap (* RHS. Pb );

Delete porig;

Return * this;

}

Another replacement solution ensures exceptional security and can handle self-assigned values: Copy and swap Technology

Class widget {

Void swap (widget & RHs );

};

Widget & Widget: Operator = (const widget & RHs ){

Widget temp (RHs );

Swap (temp );

Return * this;

}

Widget & Widget: Operator = (const widget RHs) {// another highly efficient method, by-Value

Swap (RHs );

Return * this;

}

Clause 12: Do not forget every component of an object when copying it.

1. The copying function should assign a value to "all member variables in the object" and "all base class components"

2. Do not use a copying function to implement another copying function. The common function should be put into the third function and called together by the two functions.

When writing the copying function for the derived class, you must copy its base class component.

Class Customer {

Public:

Customer (const customer & RHs );

Customer & operator = (const customer & RHs );

PRIVATE: string name;

};

Class prioritycustomer: Public customer {

Public:

Prioritycustomer (const prioritycustomer & RHs );

Prioritycustomer & operator = (const prioritycustomer & RHs );

PRIVATE: int priority;

};

Prioritycustomer: prioritycustomer (const prioritycustomer & RHs)

: Customer (RHs), // call the copy constructor of the base class. If omitted, the default constructor is called. The base class is the default.

Priority (RHS. Priority)

{}

Prioritycustomer & prioritycustomer: Operator = (const prioritycustomer & RHs ){

Customer: Operator = (RHs); // you can perform the verification test first. If a member has a pointer

Priority = RHS. priority;

Return * this;

}

[Reprint] http://www.cnblogs.com/Atela/archive/2011/04/05/2006121.html

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.