C++ final surprise review

C++ review

Class & Object

Class member function

Class member functions are those functions whose definition and prototype are written inside the class definition, just like other variables in the class definition. A class member function is a member of a class. It can manipulate any object of the class and can access all members of the object.

Code

class Box
{
    public:
    	double length;
    	double breadth;
    	double height;
	void move();
        double getVolume()
        {
            return length * breadth * height;
        }

};

class SmallBox:Box
{
    public:
	void setLength(double len);
	double getLength();
	SmallBox(double len);	//构造函数
	SmallBox(const SmallBox &obj);	//拷贝构造函数
	~SmallBox();		//析构函数
    private:
        double length1;
		double *ptr;
};

Constructor

Execute when the object is created

//构造函数
SmallBox::SmallBox(double len): length1(len)	//初始化列表
{
	//length1 = len;	//初始化列表写法等价于这个
	cout<<"SmallBox对象被创建了"<<endl;
	cout<<"初始化的len:"<<len<<endl;
	ptr = new double;
	*ptr = len;
}

Destructor

The destructor will be executed every time the created object is deleted

//析构函数会在每次删除所创建的对象时执行
SmallBox::~SmallBox()
{
	cout<<"析构函数执行了,length:"<<*ptr<<endl;
	cout<<"释放内存"<<endl;
	delete ptr;
}

Copy function

Popular understanding is to assign a class to another class

//如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数
SmallBox::SmallBox(const SmallBox &obj)
{
	cout<<"调用拷贝函数并且为指针ptr分配内存"<<endl;
	//为指针分配内存
	ptr = new double;
	*ptr = *obj.ptr;
}

use:

SmallBox sbox1(7.7);

//此时会调用拷贝函数
SmallBox box2 = sbox1;
SmallBox box3 = sbox1;

Friend function

A friend can be a function, which is called a friend function; a friend can also be a class, which is called a friend class and is modified with the friend keyword

Declare friend functions:

class Box
{
   double width;
public:
   double length;
   friend void printWidth( Box box );
   void setWidth( double wid );
};

Define friend function:

// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
   /* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
   cout << "Width of box : " << box.width <<endl;
}

Declare a friend class:

friend class ClassTwo;

Inline function

If a function is an inline function, the compiler will place a copy of the function in every place where the function is called. When the function is modified, it must be recompiled, otherwise the old code will be used and the inline function will be defined , The keyword inline needs to be placed before the function name , and the function needs to be defined before calling the function. If the defined function is more than one line, the compiler will ignore the inline qualifier

The functions defined in the class definition are all inline functions, even if the inline specifier is not used .

this pointer

Each object can use the this pointer to point to itself. The pointer is an implicit parameter of all member functions. Inside the member function, it can be used to point to the calling object

The friend function does not have this pointer, because the friend is not a member of the class. Only member functions have this pointer.

Sample code:


#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      // 构造函数定义
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      int compare(Box box)
      {
         return this->Volume() > box.Volume();
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};
 
int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2
 
   if(Box1.compare(Box2))
   {
      cout << "Box2 is smaller than Box1" <<endl;
   }
   else
   {
      cout << "Box2 is equal to or larger than Box1" <<endl;
   }
   return 0;
}

operation result:

Constructor called.
Constructor called.
Box2 is equal to or larger than Box1

Pointer to class

Sample code:

#include <iostream>
 
using namespace std;

class Box
{
   public:
      // 构造函数定义
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2
   Box *ptrBox;                // Declare pointer to a class.

   // 保存第一个对象的地址
   ptrBox = &Box1;

   // 现在尝试使用成员访问运算符来访问成员
   cout << "Volume of Box1: " << ptrBox->Volume() << endl;

   // 保存第二个对象的地址
   ptrBox = &Box2;

   // 现在尝试使用成员访问运算符来访问成员
   cout << "Volume of Box2: " << ptrBox->Volume() << endl;
  
   return 0;
}

Results of the

Constructor called.
Constructor called.
Volume of Box1: 5.94
Volume of Box2: 102

Static members of the class

We can use the static keyword to define class members as static. When we do this, it means that no matter how many objects we commonly use, there is always only one static member in memory, or in other words, all objects share the same static member.

We can't put the initialization of static members in the definition of the class. You can re-declare the static variable outside the class by :: to initialize it

Static member variables:

Sample code:

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      static int objectCount;
      Box()
      {
         // 每次创建对象时增加 1
         objectCount++;
      }
};
 
// 初始化类 Box 的静态成员
int Box::objectCount = 0;

int main(void)
{
   Box Box1();    // 声明 box1
   Box Box2();    // 声明 box2
 
   // 输出对象的总数
   cout << "Total objects: " << Box::objectCount << endl;
 
   return 0;
}

Results of the:

Total objects: 2

Static member function:

  • +Static functions can be accessed as long as they use the class name and scope resolution operator ::
  • Static member functions can only access static member data, other static member functions and other functions outside the class
  • Static member functions have a class scope, and they cannot access the this pointer of the class. You can use static member functions to determine whether certain objects of the class have been created.

The difference between static member function and ordinary member function:

  • Static member functions have no this pointer and can only access static members (including static member variables and static member functions).
  • Ordinary member functions have this pointer and can access any member in the class; while static member functions do not have this pointer.

Sample code:


#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      static int objectCount;
      // 构造函数定义
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // 每次创建对象时增加 1
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      static int getCount()
      {
         return objectCount;
      }
   private:
      double length;     // 长度
      double breadth;    // 宽度
      double height;     // 高度
};
 
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
 
int main(void)
{
  
   // 在创建对象之前输出对象的总数
   cout << "Inital Stage Count: " << Box::getCount() << endl;
 
   Box Box1(3.3, 1.2, 1.5);    // 声明 box1
   Box Box2(8.5, 6.0, 2.0);    // 声明 box2
 
   // 在创建对象之后输出对象的总数
   cout << "Final Stage Count: " << Box::getCount() << endl;
 
   return 0;
}

Results of the:

Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2

inherit

  • concept

When creating a class, you do not need to rewrite new data members and member functions, just specify that the newly created class inherits the members of an existing class. This existing class is called the base class , and the newly created class is called the derived class .

Suppose there is a base class Shape , and Rectangle is its derived class

// 基类
class Shape 
{...}

// 派生类
class Rectangle: public Shape
{...}
  • Access control and inheritance

    The derived class can access all the non-private members of the base class. Therefore, if members of the base class do not want to be accessed by member functions of the derived class, they should be declared as private in the base class.

    A derived class inherits all base class methods, except in the following cases:

    • The constructor, destructor, and copy constructor of the base class.
    • The overloaded operator of the base class.
    • Friend function of the base class.

  • Inheritance type

    We hardly use protected or private inheritance, usually public inheritance. When using different types of inheritance, follow the following rules:

    • Public inheritance (public): When a class is derived from the public base class, the base class's public member of the derived class public members of the base class to protect a member of the derived class to protect members of the base class's private members can not be directly derived class Access, but it can be accessed by calling the public and protected members of the base class .
    • Protected inheritance (protected): When a class is derived from protecting base class, the base class public and protection of the members of the derived class will be to protect members.
    • Private inheritance (private): When a class is derived from the private base class, the base class public and protection of the members of the derived class will become private members.
  • Multiple inheritance

    In layman's terms, a sub-category has multiple parent categories and the characteristics of multiple parent categories

    Syntax format:

    Use commas to separate parent classes

    class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
    {
    <派生类类体>
    };
    

    Example:

    // 基类 Shape
    class Shape {...}
    
    // 基类 PaintCost
    class PaintCost {...}
    
    // 派生类
    class Rectangle: public Shape, public PaintCost{...}
    

Overloaded operators and overloaded functions

  • The basic concept of function overloading

Functions with the same name but different formal parameters (different number, type or order of parameters) constitute an overload

Example:


#include <iostream>
using namespace std;
 
class printData
{
   public:
      void print(int i) {
        cout << "整数为: " << i << endl;
      }
 
      void print(double  f) {
        cout << "浮点数为: " << f << endl;
      }
 
      void print(char c[]) {
        cout << "字符串为: " << c << endl;
      }
};
 
int main(void)
{
   printData pd;
 
   // 输出整数
   pd.print(5);
   // 输出浮点数
   pd.print(500.263);
   // 输出字符串
   char c[] = "Hello C++";
   pd.print(c);
 
   return 0;
}

Results of the:

整数为: 5
浮点数为: 500.263
字符串为: Hello C++
  • The concept of operator overloading

An overloaded operator is a function with a special name . The function name is composed of the keyword operator and the operator symbols to be overloaded later. Like other functions, overloaded operators have a return type and a parameter list. In layman's terms, redefine the function of the operator

Box operator+(const Box&);

Declare that the addition operator is used to add two Box objects. Therefore, when using it, you need to pass in two Box objects

Box operator+(const Box&, const Box&);

Example:


#include <iostream>
using namespace std;
 
class Box
{
   public:
 
      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }
 
      void setBreadth( double bre )
      {
          breadth = bre;
      }
 
      void setHeight( double hei )
      {
          height = hei;
      }
      // 重载 + 运算符,用于把两个 Box 对象相加
      Box operator+(const Box& b)
      {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
   private:
      double length;      // 长度
      double breadth;     // 宽度
      double height;      // 高度
};
// 程序的主函数
int main( )
{
   Box Box1;                // 声明 Box1,类型为 Box
   Box Box2;                // 声明 Box2,类型为 Box
   Box Box3;                // 声明 Box3,类型为 Box
   double volume = 0.0;     // 把体积存储在该变量中
 
   // Box1 详述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 详述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Box1 的体积
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Box2 的体积
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // 把两个对象相加,得到 Box3
   Box3 = Box1 + Box2;
 
   // Box3 的体积
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}

  • Overloadable operator/non-overloadable operator

The following is a list of operators that can be overloaded:

Binocular arithmetic operators + (Addition), -(subtraction), * (multiplication), / (division),% (modulo)
Relational operator == (equal to), != (not equal to), <(less than),> (greater than>, <= (less than or equal to), >= (greater than or equal to)
Logical Operators || (logical OR), && (logical AND),! (Logical NOT)
Unary operator + (Positive),-(negative), * (pointer), & (take address)
Increment and Decrement Operator ++ (increase), – (decrease)
Bit operator | (Bitwise OR), & (Bitwise AND), ~ (Bitwise negation), ^ (Bitwise XOR),, << (Shift left), >> (Shift right)
Assignment operator =, +=, -=, *=, /= , % = , &=, |=, ^=, <<=, >>=
Space application and release new, delete, new[ ] , delete[]
Other operators () (function call), -> (member access),, (comma),

The following is a list of operators that cannot be overloaded:

  • .: Member access operator
  • . , -> : Member pointer access operator
  • ::: Domain operator
  • sizeof: length operator
  • ?:: Conditional operator
  • #: preprocessing symbol

Polymorphism

As the name implies, it means multiple forms, such as animals. The following subcategories include cats, dogs and sheep, etc..., cats, dogs and sheep are multiple forms of animals

C++ polymorphism means that when a member function is called, different functions will be executed according to the type of the object calling the function .

Sample code:

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};
class Triangle: public Shape{
   public:
      Triangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};
// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
 
   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();
 
   // 存储三角形的地址
   shape = &tri;
   // 调用三角形的求面积函数 area
   shape->area();
   
   return 0;
}

It will produce the following results:

Parent class area
Parent class area

Details, the above output result is wrong, the cause of the error is that the calling function area() is set as the version in the base class by the compiler. This is the so-called static polymorphism , or static linking -function calls are prepared before the program is executed All right. Also known as early binding , we only need to add the virtual keyword before the area() method in the Shape class ;

The modified output:

Rectangle class area
Triangle class area

At this point, the compiler looks at the content of the pointer, not its type

Each subclass has an independent implementation of the function area(). This is how polymorphism is generally used. With polymorphism, you can have multiple different classes, all with the same name but with different implementation functions, and the parameters of the function can even be the same.

  • Virtual function

    A virtual function is a function declared in the base class using the keyword virtual . When redefining a virtual function defined in a base class in a derived class, it will tell the compiler not to link to the function statically.

  • Pure virtual function

    You may want to define a virtual function in the base class so that you can redefine the function in the derived class to better apply to the object, but you cannot give a meaningful implementation of the virtual function in the base class. Pure virtual functions are used.

    Virtual functions must not be defined. Pure virtual functions are used to standardize the behavior of derived classes, namely interfaces . A class containing pure virtual functions is an abstract class. An abstract class cannot define an instance, but it can declare a pointer or reference to a concrete class that implements the abstract class.

    We can rewrite the virtual function area() in the base class as follows:

    class Shape {
       protected:
          int width, height;
       public:
          Shape( int a=0, int b=0)
          {
             width = a;
             height = b;
          }
          // pure virtual function
          virtual int area() = 0;
    };
    
    

    = 0 tells the compiler that the function has no body and the virtual function above is a pure virtual function .

Interface (abstract class)

  • concept

    If at least one function in the class is declared as a pure virtual function, then this class is an abstract class. Pure virtual functions are specified by using "= 0" in the declaration, as shown below

    
    class Box
    {
       public:
          // 纯虚函数
          virtual double getVolume() = 0;
       private:
          double length;      // 长度
          double breadth;     // 宽度
          double height;      // 高度
    };
    
    

    Subclasses of abstract classes must rewrite all pure virtual functions

  • Examples of abstract classes:

    
    #include <iostream>
     
    using namespace std;
     
    // 基类
    class Shape 
    {
    public:
       // 提供接口框架的纯虚函数
       virtual int getArea() = 0;
       void setWidth(int w)
       {
          width = w;
       }
       void setHeight(int h)
       {
          height = h;
       }
    protected:
       int width;
       int height;
    };
     
    // 派生类
    class Rectangle: public Shape
    {
    public:
       int getArea()
       { 
          return (width * height); 
       }
    };
    class Triangle: public Shape
    {
    public:
       int getArea()
       { 
          return (width * height)/2; 
       }
    };
     
    int main(void)
    {
       Rectangle Rect;
       Triangle  Tri;
     
       Rect.setWidth(5);
       Rect.setHeight(7);
       // 输出对象的面积
       cout << "Total Rectangle area: " << Rect.getArea() << endl;
     
       Tri.setWidth(5);
       Tri.setHeight(7);
       // 输出对象的面积
       cout << "Total Triangle area: " << Tri.getArea() << endl; 
     
       return 0;
    }
    
    

    It will produce the following result:

    Total Rectangle area: 35
    Total Triangle area: 17
    

template

Templates are blueprints or formulas for creating generic classes or functions

  • Function template

Grammatical form:

template <typename type> ret-type func-name(parameter list)
{
   // 函数的主体
}

type is the placeholder name of the data type used by the function . This name can be used in the function definition

Example:


#include <iostream>
#include <string>
 
using namespace std;
 
template <typename T>
inline T const& Max (T const& a, T const& b) 
{ 
    return a < b ? b:a; 
} 
int main ()
{
 
    int i = 39;
    int j = 20;
    cout << "Max(i, j): " << Max(i, j) << endl; 
 
    double f1 = 13.5; 
    double f2 = 20.7; 
    cout << "Max(f1, f2): " << Max(f1, f2) << endl; 
 
    string s1 = "Hello"; 
    string s2 = "World"; 
    cout << "Max(s1, s2): " << Max(s1, s2) << endl; 
 
   return 0;
}

  • Class template

Syntax format:

template <class type> class class-name {
.
.
.
}

type is the placeholder type name, which can be specified when the class is instantiated. You can use a comma-separated list to define multiple generic data types.

Example:


#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
 
using namespace std;
 
template <class T>
class Stack { 
  private: 
    vector<T> elems;     // 元素 
 
  public: 
    void push(T const&);  // 入栈
    void pop();               // 出栈
    T top() const;            // 返回栈顶元素
    bool empty() const{       // 如果为空则返回真。
        return elems.empty(); 
    } 
}; 
 
template <class T>
void Stack<T>::push (T const& elem) 
{ 
    // 追加传入元素的副本
    elems.push_back(elem);    
} 
 
template <class T>
void Stack<T>::pop () 
{ 
    if (elems.empty()) { 
        throw out_of_range("Stack<>::pop(): empty stack"); 
    }
    // 删除最后一个元素
    elems.pop_back();         
} 
 
template <class T>
T Stack<T>::top () const 
{ 
    if (elems.empty()) { 
        throw out_of_range("Stack<>::top(): empty stack"); 
    }
    // 返回最后一个元素的副本 
    return elems.back();      
} 
 
int main() 
{ 
    try { 
        Stack<int>         intStack;  // int 类型的栈 
        Stack<string> stringStack;    // string 类型的栈 
 
        // 操作 int 类型的栈 
        intStack.push(7); 
        cout << intStack.top() <<endl; 
 
        // 操作 string 类型的栈 
        stringStack.push("hello"); 
        cout << stringStack.top() << std::endl; 
        stringStack.pop(); 
        stringStack.pop(); 
    } 
    catch (exception const& ex) { 
        cerr << "Exception: " << ex.what() <<endl; 
        return -1;
    } 
}

Results of the:

7
hello
Exception: Stack<>::pop(): empty stack

Guess you like

Origin blog.csdn.net/weixin_44829930/article/details/112446672