C + + Learning Notes 1

C + + learning notes

object-oriented

Input and output

#include <iostream>
using namespace std;
int main(){
    char s[30];
    cout << "say someting to echo:" << endl;
    cin >> s;
    cout << s << endl;
    return 0;
}

Header files and class declarations

Defensive statement

#ifndef __COMPLEX__
#define __COMPLEX__

/*something*/

#endif

forward declaration

class and function, but not implemented

Class declaration (class body)

Specifically describe the content of the class, including the declaration of member functions

Member function definition

Implement the contents of member functions. Examples are as follows:

#ifndef __BOX__
#define __BOX__
 /*It is only used to show the definition of member functions, not the most standardized way*/
class Box
{
   public:
      double length;   // length
      double breadth;  // width
      double height;   // height
      // Member function declaration
      double get(void);
      void set( double len, double bre, double hei );
};
// Member function definition
double Box::get(void)
{
    return length * breadth * height;
}
 
void Box::set( double len, double bre, double hei)
{
    length = len;
    breadth = bre;
    height = hei;
}

#endif

class template

The type of some member variables in the class can be written with a label at the time of declaration and determined at the time of concrete instantiation.

template<typename T>
class Box
{
   public:
      T length;   // length
      T breadth;  // width
      T height;   // height
      // Member function declaration
      T get(void);
      void set( T len, T bre, T hei );
};

Inline function (inline)

Of course, the member function definition can also be completed in the class declaration (I often do this in java). Such functions will become inline candidates. This way of writing is not good. The reason will be explained later.

For the member function definition outside the class declaration, the inline keyword can be added before the function name (note that it should be before the function definition rather than the function declaration, also known as the keyword for Implementation). The function will become an inline candidate.

To truly become an inline function, there are the following restrictions:

  • It cannot exceed one line. If it exceeds, the compiler will ignore the inline (in doubt)
  • No loops, switch
  • Cannot be a recursive function

Its essence is not to define different positions. The inline function is related to efficiency. Calling a small function may cause some unnecessary stack space consumption. In order to improve efficiency, such a small function will be replaced by an appropriate short code by the compiler during compilation to reduce the loss.

inline is just a suggestion to the compiler, which may not be adopted by the compiler. If it is too complex, it will still be treated as a real function.

Therefore, if the function written in the class definition is short enough, it may be inlined; If you write a complex function, you should put it outside the class definition.

Be careful with inline functions and believe in the choice of compiler.

Access modifier

An access modifier is added to the class definition.

public indicates that the members of this part are publicly available, and other functions and statements can be used at will. That is, functions and variables can be used directly

Private indicates that the members of this part are private and can only be called by the instance itself or friend functions. Other functions and statements cannot be accessed and modified directly. To access, you need to use the provided public function.

Protected is similar to private. The difference of this protected member is that it is accessible in subclasses. (supplemented by inheritance and derivation)

Generally, public is used to declare some functions for external use. private is used to declare member variables and functions that cannot be called by others. The reason for this distinction is to improve the degree of packaging. Examples are as follows:

class complex
{
public:
  complex (double r = 0, double i = 0): re (r), im (i) { }
  double real () const { return re; }
  double imag () const { return im; }
private:
  double re, im;
  friend complex& __doapl (complex *, const complex&);
};

Constructor

Constructor is a function under public in the class declaration.

A better way to write is to use the initial column, as follows:

class complex
{
public:
  complex (double r = 0, double i = 0)
      : re (r), im (i)
  { }
  //slightly
};

If there is no assignment during construction, the default argument is used.

This way of writing is faster than using the function form of assignment. Because there is an initialization process before instantiating an object, in which the assignment is faster than calling the constructor. Of course, the constructor is also written correctly, as follows:

class complex
{
public:
  complex (double r = 0, double i = 0){
      re=r;
      im=i;
  }
  //slightly
};

There can be many constructors, that is, overload.

class complex
{
public:
  complex (double r = 0, double i = 0)
      : re (r), im (i)
  { }
  complex() 
      : re(0),im(0)
  { }
  //slightly
};

There is a certain contradiction in the way it is written here. The first constructor has explained that if no parameter is provided, the default argument 0 is used; The second rewrites this sentence again. It is unnecessary and will fail to compile.

It can be written as follows:

class complex
{
public:
  complex (double r = 0, double i = 0): re (r), im (i) { }
  complex(double a) 
      : re(a),im(a)
  { }
};

The second constructor means that if only one parameter is given, the real and imaginary parts are set to this parameter. (it's really useless)

Can the constructor be placed in the private area? It sounds nonsense, so you can't instantiate the object? Write a class that does not need to be instantiated? In fact, it is possible to do so.

In a design pattern called singleton, a class is designed, which is responsible for creating an object and only one, and provides some functions to access the object. Externally, you can use it directly without instantiation, and share an instance globally. The key to this design pattern is that constructors are private functions. It is generally used in some scenarios where the number of instances is limited to avoid frequent creation and recycling of globally used instances. The code screenshot is as follows:

Constant member function and const keyword usage

Member functions that provide member values (some around), such functions should be marked const. Calling a function does not and cannot change the contents of the object. Examples are as follows:

double real() const {return re;}
double imag() const {return im;}
const int  a = 7;

The const tag of a function is different from that of a variable. The const tag of a function is placed after the function name and before the curly braces, and the const tag of a variable is placed before the type.

On the one hand, this operation is to protect member variables, on the other hand, it also avoids the problems that may occur when a const object obtains member variables.

Further, what if a member function is marked const, but you want to change the member variable in the definition? When declaring a member variable, you can add the mutable keyword in front of it. This member can be in constant change and will not be limited by the const member function.

The left fixed value means that the variable value cannot be changed. Right orientation means that the memory address cannot be changed, but the content can be changed. Of course, you can write both to ensure that the content and memory address do not change. Left and right means that const is around *

const int* p = 8;

int a = 8;
int* const p = &a;

int a = 8;
const int* const  p = &a;

Parameter passing, value passing or reference passing?

It's good to pass references. After all, the size of the pointer is fixed, and the size of the object may be large, causing overhead. It is also generally recommended to write as a biographical reference.

Sometimes there is no need to pass references, especially some simple variables and data types.

If you want the passed in parameters not to be changed, use const to decorate them. There are the following situations:

void function(const int Var); //The passed parameter cannot be changed in the function (meaningless, because Var itself is a formal parameter)

void function(const char* Var); //What the parameter pointer refers to is constant and immutable

void function(char* const Var); //The parameter pointer itself is constant and immutable (meaningless, because char* Var is also a formal parameter)


void function(const TYPE& Var); //Reference parameters are constant and immutable within a function

I saw the type name for the first time here & this way of writing. This means that this type of reference is different from passing a pointer, but it can be understood as a pointer. In the sub function, the formal parameter is used as the variable name, and the change will also affect the argument.

In C + +, whether a parameter is a pointer or a reference is different. It is distinguished by * and &, which will not be discussed here.

Return value, value or reference?

It also needs serious consideration. If only one calculation result is required, the value should be passed. Even if the result is an object, the value should also be passed. If the reference is passed, it is invalid because the reference has died after the end of the function.

But sometimes it is also necessary to pass a reference. For example, this reference is passed in the parameter and returned after processing. This is OK.

friend function

private and protected member variables cannot be called externally, but can only be called by themselves or friend functions. friend

Meta functions are defined outside the class and have access to the above member variables. The prototype of a friend function has appeared in the class definition, but it is not a member function.

Friend class means that the whole class and members are friends and can be accessed by friend classes.

Examples are as follows:

class Box
{
    friend class Box2;  //Box2 is a friend class of box. Box can directly access any member of box.
   double width;
public:
   double length;
   friend void printWidth( Box box );
   void setWidth( double wid );
};

// Please note: printWidth() is not a member function of any class. It is not written as Box::printWidth, and there is no need to use an object when calling
void printWidth( Box box )
{
   /* Because printWidth() is a friend of Box, it can directly access any member of the class */
   cout << "Width of box : " << box.width <<endl;
}

The friend function does not have this pointer. You need to pass in the used object as a parameter. If it is a static member, a global variable, or a global object, no parameters are required.

In addition, objects of the same class are friends with each other and can call each other's private variables. The code screenshot is as follows:

operators overloading

Member function method

The member function has a hidden parameter, this, which refers to the caller. This is a pointer. Code examples are as follows:

//do assignment plus
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 )
}

c2+=c1;

Note that the return value of the operator function is also a reference. If you don't care about the return value, it's OK to set it to void. However, for the following concatenated operators:

c3+=c2+=c1;

The return value is required, as is the return value of c2+=c1.

Non member function method

For an operator of a class, you can only use one writing method of member or non member, not two. The compiler automatically matches.

Non member functions do not have this pointer, which is actually equivalent to writing global functions.

inline complex operator + (const complex& x, const complex& y)
{
  return complex (real (x) + real (y), imag (x) + imag (y));
}

inline complex operator + (const complex& x, double y)
{
  return complex (real (x) + y, imag (x));
}

inline complex operator + (double x, const complex& y)
{
  return complex (x + real (y), imag (y));
}

//Corresponding to the following three usages
c2=c1+c2;
c2=c1+5;
c2=7+c1;

The return value is value and cannot be a reference. This is the same as the return value mentioned earlier. Because after addition, the value should be returned instead of the local reference variable of the addition function, and that reference will be destroyed. You also need a place to save this object and use temporary objects. The previous + = return value is a reference because the return value has been placed in an incoming reference. Of course, the return reference is OK.

The same operator can have different effects depending on the number of parameters, as follows:

inline complex operator + (const complex& x)
{
  return x;
}

inline complex operator - (const complex& x)
{
  return complex (-real (x), -imag (x));
}//negate

For < <, only non member functions can be written. The code is as follows:

#include <iostream.h>
ostream& operator << (ostream& os, const complex& x){
    return os << '(' << real(x) << ','
              <<image(x)<<')';
}

os cannot be written as const because the output is changing the os.

In order to output in series, the return value should be osteam &, which can continue to accept < <, so it should be of the same type as cout.

Temporary object

The class name typename() is equivalent to creating a temporary object with a build function. The life cycle is very short, just to pass values. It doesn't matter if there is no name.

The quotation is very good

The sender does not need to know that the receiver receives as a reference reference.

For example, the doapl function returns * ths, which is an object, but the declared return value, that is, the receiver, is in the form of reference. There is no problem with this writing. The specific contents are handed over to the compiler.

For another example, when using overloaded operators, c1 is also passed in as an object, but the parameters are written as references, which is no problem.

Global function

Without class name. However, when using, the object should be passed in as a parameter, unlike member functions, which can be clicked directly.

Some writing methods to pay attention to

  • Constructor to write initialization
  • Should const be added to member functions
  • Try to pass parameters by reference. Do you want const
  • Is the return value a value or a reference
  • The data should be private and the function should be public

Keywords: Cpp

Added by scrtagt69 on Sat, 08 Jan 2022 06:40:55 +0200