Tips for C + + learning

Source: Internet
Author: User

Two classic categories of classes
Class without pointer member (s)
Complex
Class with pointer member (s)
String


Defensive statements in the header
Complex.h
#ifndef __complex__
#define __complex__
Code
#endif

Inline Function
function is automatically a candidate for the inline function if it is defined within the class body
Functions defined outside the class body need to be prefixed with the inline keyword to suggest that the compiler compile it as an inline function


Constructor (ctor, constructor)
Class Complex
{
Public
Complex (Double r = 0, double i = 0)//default argument
: Re (r), IM (i)//Initial Value column
{ }
};
The constructor initializes the variable with the initial value column, and it is best not to use "=" in the function body to assign a value
The construction of a variable has two phases: initialization, assignment, so the mechanism for using the initial Value column is more efficient (eliminating an assignment phase)
ctor can have multiple overloads


ctor on the private zone .
Singleton single-Case mode
Class A
{
Public a& getinstance ();
Setup () {...};
Private
A ();
A (const a& RHS);
...
};

a& a::getinstance ()
{
static A;
return A;
}

A::getinstance (). Setup ();
An instance of an object cannot be created directly by the outside world, but only through functions within class.


Const member function (constant member functions)
Double Real () const {return re;}
The CONST keyword declaration here will certainly not change the member variables within the class re

For example: If you do not write the above const, the following code block will compile the error
{
Const complex C1 (1, 2)
cout << c1.real () << c1.imag ();
}
Because the user creates a const object C1, which specifies that C1 is a constant, where the member variable will also be const, which is not likely to be changed, and when the member function real () is called, it is not declared to be a constant member function, that is, the member variable re in the class is "likely" to be changed, It's a contradiction.


parameter pass: pass by value VS. Pass by reference (to const)
Passing a copy parameter that is unchanged by value, passing an address that is equivalent to passing a parameter by reference (the underlying is a pointer), so it is generally more efficient
For example:complex& operator + = (const complex&);
The goal is to pass in a complex object (the reference) by reference, and declare that the passed-in object itself prohibits the function from being modified, [pass by reference (to const)]
Transfer of parameters as far as possible by reference


return value pass: pass by value VS. Pass by reference
Under what circumstances can pass by reference (to const)?
Under what circumstances can I return by reference?
For example, after the "__DOAPL" function, its first parameter will be changed, the second parameter will not be changed
At this point the second parameter can pass by the reference (to const), the first parameter can return by reference

The following is a good example of a return by reference:
Inline complex& __DOAPL (complex* ths, const complex& R)
{
Ths->re + = R.re;
Ths->im + = r.im;
return *ths;
}
Inline complex& Complex::operator + = (const complex& r)
{
Return __DOAPL (this, r);
}
Note that the first parameter is passed in a pointer, which is not a local variable created temporarily in the body of the function, but a variable that already exists outside the function, so it can be return by reference

Under what circumstances cannot return by reference?
The local variable in the function body cannot return by reference. Because when the function ends, its local variable also dies, and if return by reference an "address" point to the content is broken
For example:
Inline complex& __DOAPL (complex* ths, const complex& R)
{
Return (Ths->re + r.re);
}


Friend (Friend)
The private member of the class Re and IM cannot be directly used by the outside world (can be used by the in-class function), but the friend function within the class can get the private member of its "friends" directly
Class Complex
{
Private
double Re, im;
Friend complex& __DOAPL (complex*, const complex&);
};

Inline complex& __DOAPL (complex* ths, const complex& R)
{
Ths->re + = R.re; Free access to friend's private members
Ths->im + = r.im;
}

Each objects of the same class is mutually friends (friend)
Class Complex
{
Public
int func (const complex& param)
{return param.re + param.im;}
The private members of "friends" are taken directly here.
Private
double Re, im;
};

{
Complex C1 (2,1);
Complex C2;
C1 and C2 each other as friends
C2.func (C1);
}


write a small summary of a class
Data must be placed in private
Parameter passing and return values are passed as far as possible by reference
The member function in class body needs to be added const (constant member function)
ctor try to use its initial value-list mechanism


Big three three special functions
Copy construction, copy assignment, destructor
Be sure to check if self assignment in copy assignment
Inline string& string::operator= (const string& STR)
{
if (this = = &str)
return *this;
//...
}


Memory Management
NEW: Allocate memory first, then call ctor
complex* pc = new Complex;
The compiler translates to:
Complex *pc;
void* mem = operator new (sizeof (Complex)); Allocating memory
PC = Static_cast<complex*> (MEM); Forcing type conversions
(Pc->complex::compelex); Call constructor
Complex::compelex (the PC is equivalent to hiding this pointer in this one);

Delete: Call Dtor First, then release memory
Delete pc;
The compiler translates to:
Complex::~complex (PC); Destructors
operator delete (PC); Freeing memory

Note: "Operator new ()" and "operator delete ()" are special C + + system functions that are used to allocate memory, which internally calls malloc (), which frees memory and calls free ()


static data members and static member functions
There is only one copy of static data in class (present in "Global/Static Storage")
Static functions do not have this pointer, so a static function can only handle static data that resides in a global/static store, and cannot access non-static data members within class
Example: Designing a bank Account
Class Account
{
Public
static double m_rate; Interest rates
static void Set_rate (const double& x)
{m_rate = x;}
};

Double account::m_rate = 0.01; Assignment of static data members 1 (initialization of static data members)

int main ()
{
Account::set_rate (0.02); Assignment of static data members 2 (call static function by class name)

Account A; Assignment of static data members 3 (call static function via object)
A.set_rate (0.03);
}


class Template
Example:
Template<typename t>
Class Complex
{
Public
Complex (T r = 0, t i = 0)
: Re (r), IM (i)
{ }
Private
T Re, im;
};

{
Complex<double> C1 (2.0, 1.0); "T" in class is replaced with "double"
Complex<int> C2 (2, 1); "T" in class is replaced with "int"
}


function Template
For example, there is a stone class:
Class
{
Public
Stone (int w, int h, int we)
: Width (w), Height (h), weight (We)
{ }
BOOL operator < (const stone& RHS) const
{return weight < rhs.weight;}
Private
int width, height, weight;
};

To create two stone objects, and compare the weight of stone:
Stone R1, R2 (2,3,4);
R3 = min (r1, R2);

If you have a function template:
Template<class t>
Inline const t& min (const t& A, const t& b)
{
Return B < A? b:a;
}
The "T" in the function template will be replaced with the class name "stone".
Because R1 and R2 are stone classes, the compiler will argument deduction parameter derivation for the function template

In the case of object size comparisons, because "T" is "stone", then call stone::operator<


Combination and Inheritance

Composition (composite) means "has-a"


Construction and destruction under the compound relation
Constructed from the Inside out
The container constructor first calls the component default constructor, and then executes its own

The destruction by the outer and inner
The destructor of the container first executes itself, and then the destructor of the component is called.


Delegation (commissioned) or composition by reference
Bridging mode (handle/body mode) or Pimpl (Pointer to implementation)
There is a string class, in addition to the necessary Declaration of class, the actual implementation is defined in another class Stringrep, in the string class set a pointer to the concrete implementation of the class Stringrep

File string.hpp
Class Stringrep; Statement
Class String
{
Public
String (); Default constructs
String (const char* s); Copy Construction
String (const string& s); Copy Construction
string& operator= (const string& s); Copy Assignment
~string (); Destruction
Private
Stringrep* Rep; Handle/body (Pimpl)
}

File String.cpp
#include "string.hpp"
namespace {
Class Stringrep {
Friend class String;
Stringrep (const char* s);
~stringrep ();
int count;
Char* Rep;
};
}

Inheritance (inheritance) means "is-a"

Constructed from the Inside out
The constructor of the Derived (derived class/subclass) first calls the base (base class/parent Class) of the default constructor and then executes its own

The destruction by the outer and inner
The destructor of derived executes itself first, and then calls base on the destructor

The base class Dtor must be virtual, or undefined will appear behavior


virtual function and polymorphic
Inheritance (inherited) with virtual functions (virtual function)
non-virtual function: You do not want derived class to redefine (override/) it;
Virtual function: you want derived class to redefine (override/) it, and you have a default definition for it;
Pure virtual function: you want derived class to be redefined (override/) it, you don't have a default definition for it.


conversion function Conversion Functions
Class fraction
{
Public
fraction (int num, int den=1)
: M_numerator (num), M_denominator (DEN) {}
operator double () const
{
Return (double) (m_numerator*1.0/m_denominator);
}
Private
int m_numerator; Molecular
int m_denominator; Denominator
};

When the following code block is executed:
{
Fraction f (3,5);
Double d=4+f;
}
First construct a fraction 3/5, then try to add double and fraction, and get a double value
The compiler checks to see if the double+fraction operator+ is defined, or if the operator+ function is called, the compiler checks if class fraction defines a conversion function for fraction to double. If the conversion function is called, the compilation error


non-explicit-one-argument ctor
Class fraction
{
Public
fraction (int num, int den=1)
: M_numerator (num), M_denominator (DEN) {}
Fraction operator+ (const fraction& f)
{
return fraction (...);
}
Private
int m_numerator; Molecular
int m_denominator; Denominator
};

When the following code block is executed:
{
Fraction f (3,5);
Fraction d2=f+4;
}
The left operand is fraction, the right operand is double, and the left operand of the operator+ function is fraction (the implied this pointer), the right operand is also fraction, so the compiler tries to call Non-explicit ctor to "4" Fraction (4,1) ", and then call operator+


coexistence of conversion function and Non-explicit-one-argument ctor
Class fraction
{
Public
fraction (int num, int den=1)
: M_numerator (num), M_denominator (DEN) {}

Conversion function
operator double () const
{return (double) (m_numerator*1.0/m_denominator);}
Non-explicit-one-argument ctor
Fraction operator+ (const fraction& f)
{return fraction (...);}

Private
int m_numerator; Molecular
int m_denominator; Denominator
};

When the following code block is executed:
{
Fraction f (3,5);
Fraction d2=f+4;
}
Because either of these can be called, generating two semantics, compilation error


explicit-one-argument ctor
Class fraction
{
Public
explicit fraction (int num, int den=1)
: M_numerator (num), M_denominator (DEN) {}
Fraction operator+ (const fraction& f)
{return fraction (...);}
Private
int m_numerator; Molecular
int m_denominator; Denominator
};

When the following code block is executed:
{
Fraction f (3,5);
Fraction d2=f+4; [ERROR] changed to "Fraction d2=f+fraction (4);" Available through
}
will be error, because in the "explicit" keyword, the argument of the operator+ function must be fraction type, even if only an int parameter can be constructed fraction (for example, fraction (4) is 4/1), But explicit still does not allow this behavior to occur


Pointer-like class about smart pointers
The smart pointer encapsulates a generic pointer into a class, and overloads * and-&GT, enabling the smart pointer not only to operate a generic pointer, but also to extend other operations within the class
General framework for Smart pointers:
Template<class t>
Class shared_ptr
{
Public
t& operator* () const
{return *px;}

t* operator-> () const
{return px;}

shared_ptr (t* P): PX (p) {}//constructor usually accepts a "real pointer" to construct the "smart pointer"
Private
t* px; Pointer to class T type
//...
};

Equivalent to having a "smart pointer" shared_ptr (actually a class) that contains a "real pointer" px (a private variable; A pointer to a class T type)

Examples of Use:
struct FOO
{
//...
void method (void) {...}
};

Shared_ptr<foo> sp (new Foo);
Foo f (*SP);
Sp->method ();
First, declare a smart pointer SP that points to the class Foo type;
*SP then returns the reference of the *px (class Foo object) to create the class Foo object F through the copy constructor of class Foo
Finally,sp-> will return px (a generic pointer to class Foo type), so Sp->method () is equivalent to Px->method ()


Pointer-like class about iterators
struct __list_node//list element
{
void* prev;
Void* Next;
T data; Here T is assumed to be a struct Foo
}

struct __list_iterator//list iterator
{
//...
typedef __list_node<t>* LINK_TYPE;
Link_type node; Pointer to __list_node object

typedef t& Reference
Reference operator* () const
{
Return (*node). data;
}

typedef t* Pointer
Pointer operator-> () const
{
Return & (Operator* ()); The operator* function in class is called to return a T object (the reference)
Then use the & address to return a pointer of type t*
}
In addition, iterators not only need to process * and-&GT, generally also need to deal with + +-operation, etc., here does not extend the ...
};

Examples of Use:
List<foo>::iterator ite;
Ite->method ();
First, apply an iterator ite, which is a linked list of element type class Foo
Then, there is an action: Ite->method (), call the member function of Class Foo via iterator ite method ()
It means to call Foo::method ();
Equivalent (*ite). method (); Because *ite will get a Foo object;
Equivalent to (& (*ite))->method (), Because & (*ite) obtains a pointer to Foo object, and finally calls method () through the pointer;

Because "Ite->method ()" Ultimately corresponds to "(& (*ite))->method ()", in response to this operational requirement, this is why the operator-> in the struct __list_iterator Reason for function notation ["& (Operator* ())" Response "& (*ite)"]


adjourned

Tips for C + + learning

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.