C + + -------------- > on the eighth day, C + + keywords, exception handling, conversion functions, smart pointers

Posted by btfans on Sat, 15 Jan 2022 01:24:43 +0100

1 c + + keyword


1.1 explicit keyword
Function: used to modify the constructor in the class to prevent implicit type conversion of single parameter constructor
(convert basic data type to class type)
Features: 1. It can only modify the constructor in the class
2 explicit keyword is only valid for the constructor of one parameter. If the constructor parameter is greater than or equal to 2, the keyword is invalid. (the multi parameter constructor itself does not have implicit type conversion)

#include <iostream>

using namespace std;

class demo
{
private:
    int a;
public:
    explicit demo(int x)
    {
        a=x;
        cout<<"demo(int x)------------------\r\n";
    }
    ~demo()
    {
        cout<<"~demo()----------\r\n";
    }
    void getint()
    {
        cout<<"a=="<<a<<endl;
    }
};

int main()
{
    //Constructor is not preceded by explicit,1 has implicit type conversion
    //demo obj=1;// Equivalent to demo obj1(1);demo obj=obj1;
    //The constructor is preceded by explicit, and the object can only be defined by standard definition methods
    demo obj(2);
    obj.getint();//a=2

    return 0;
}


1.2 override keyword
If a virtual function is defined in the base class and the virtual function is to be rewritten in the subclass, the override keyword will help you check whether the rewritten virtual function name is consistent with the virtual function name of the base class. If it is inconsistent, the compilation will report an error.
Note: override should be added after the subclass override function

#include <iostream>

using namespace std;

class base
{
public:
    base()
    {
        cout<<"demo()-----------------\r\n";
    }
    ~base()
    {
        cout<<"~base()----------------\r\n";
    }
    virtual void func()
    {
        cout<<"base::func()----------\r\n";
    }
};

class sub:public base
{
public:
    sub()
    {
        cout<<"sub()-----------\r\n";
    }
    ~sub()
    {
        cout<<"~sub()-----------\r\n";
    }
    virtual void fun() override
    {
        cout<<"sub::func()-------------\r\n";
    }
};

int main()
{
    base *p=new sub;
    //p->func();

    return 0;
}


    1.3 final
When you don't want a class to be inherited or a virtual function to be rewritten, you can add the final keyword after the class name and virtual function. After adding, this class is a final class (the final class cannot generate subclasses); This virtual function is a final virtual function (final virtual functions cannot be overridden)

#include <iostream>

using namespace std;

class base
{
    virtual void func()
    {
        cout<<"base::func()--------\r\n";
    }
};

class sub:public base
{
    void func() final//func() is overridden in a sub class and is the last time it is overridden, so sub classes can no longer override func()
    {
        cout<<"sub::func()---------\r\n";
    }
};

class sua final:public base//sua cannot be inherited
{
    void func()
    {
        cout<<"sua::func()--------\r\n";
    }
};

class sua1:public sua
{
    void func()
    {
        cout<<"sua1::func()--------\r\n";
    }
};

#if 0
class sub1:public sub
{
    void func()
    {
        cout<<"sub1::func-----------\r\n";
    }
};
#endif

int main()
{
    //sub obj;
    sua obj1;

    return 0;
}


    1.4inline
Inline refers to inline. It is used to modify the member function in the class. The modified member function is called inline function
Understanding inline as a special macro for paired functions in C + + is an improvement on C's function macros. For constant macros, C + + provides const instead. For function macros, C + + uses inline. Using function macros has less overhead than using functions directly, so it is generally recommended to define short and frequently called member functions as inline functions.
How to define inline functions? Add inline before the function definition.
    
Features of inline functions:
1. The function body has simple functions, short code and frequent calls
2 inline functions are macro functions and macros. When used, they only need to be replaced by macros, so the system overhead is small. (inline functions are expanded at compile time)
Note: 1. Inline must be used with the function definition. If it is only used with the function declaration, inline will not work
2 if the code of the function body is too long or there are loop statements, if statements, switch statements or recursive algorithm statements in the function body, this function should not be designed as an inline function.
3 inline function is only a suggestion to the compiler. Whether it can be really inline depends on the compiler

#include <iostream>

using namespace std;

class demo
{
public:
    inline void func()  //Inline function
    {
        cout<<"demo::func()-----------\r\n";
    }
    void func1();//Do not add inline when declaring
};

inline void demo::func1()
{
  cout<<"demo::func1()----------\r\n";
}

int main()
{
    demo obj;
    obj.func();
    obj.func1();

    return 0;
}


2 exception handling -- exception handling mechanism provided by C + + language


Initiator of equipment exception (alarm) -- initiated by hardware itself
Anomaly detection code -- "APP detection"
Exception handling function -- exception handling
The c + + exception handling mechanism consists of three parts: try exception checking - "throw exception" -- "catch exception (exception handling)
c + + standard exception handling mechanism: try -- > throw -- > catch
         try
{/ / check statement
if (error)
throw exception;
    }
Catch (exception type)
    {
Handling exceptions;
    }
Catch (exception type)
    {
Handling exceptions;
    }
    . . . . . .  

#include <iostream>
#include <stdexcept>

using namespace std;
int divtmp(int a,int b)
{
    if(0==b)
    {
        //Exception, invalid parameter exception
        throw(invalid_argument("Divisor cannot be zero"));
    }
    return a/b;
}

int main()
{
    try
    {
        int a=10,b=0;
        int ret=divtmp(a,b);
        cout<<"ret="<<ret<<endl;
    }
    catch(invalid_argument&err)//err is an object defined in the C + + standard library
    {
        //Handling exceptions
        cout<<"err="<<err.what()<<endl;
    }
    catch(int err)  //Integer exception
    {
        cout<<"err=====\r\n";
    }
    catch(...)     //Other exceptions
    {
        cout<<"no except--------\r\n";
    }
    return 0;
}


3 conversion function -- > type conversion


c + + provides a type conversion function to convert the object of one class into data of another type, which is the essence of the conversion function
It is operator overloading, but the overloaded operator is not a built-in operator, but a special custom type such as class name
Type: 1 user defined conversion function
Format: operator type name ()
{function body;}
Basic rules of conversion functions: 1. Conversion functions can only be member functions, with no return value and no parameters
2. Class type cannot be converted to void type, nor can it be converted to array or function type
The conversion function is usually defined in const form because it does not change the value of any member

//Custom conversion function
class demo
{
public:
    demo(int a):x(a)
    {
        cout<<"demo(int a)----------\r\n";
    }
    ~demo()
    {
        cout<<"~demo()-------------\r\n";
    }
    operator int() const
    {
        return this->x;
    }
private:
   int x;
};

class demo1
{
public:
    demo1(int a,int b):x(a),y(b)
    {
        cout<<"demo1(int a,int b)----------\r\n";
    }
    ~demo1()
    {
        cout<<"~demo1()-------------\r\n";
    }
    operator double() const
    {
        return ((double)x/y);
    }
private:
   int x;
   int y;
};

int main()
{
    demo obj('a');
    int temp=obj;
    cout<<"temp="<<temp<<endl;

    demo1 obj1(3,5);
    double ret=10+obj1;
    cout<<"ret="<<ret<<endl;

    return 0;
}


2 standard conversion function
      1 reinterpret_cast: it can convert objects of different types, and can also convert pointer types into integer types (it can convert pointers and references of different data types)
     2 const_cast: you can convert constant pointers or constant references to very pointers or very references
     3  static_cast: it can be used to convert between basic data types or between objects with inheritance relationship
     4 dynamic_cast: you can convert pointers or references with inheritance relationships
      

​
//Standard transformation function
#if 0
int main()
{
    int a=10;
    const int *p=&a;//p is a constant pointer
    cout<<"*p="<<*p<<endl;
    //*p=20;// Error, the value of * P cannot be modified
    int *q=const_cast<int *>(p);
    *q=20;
    cout<<"a="<<a<<endl;
    cout<<"*q"<<*q<<endl;

    return 0;
}
#endif
class base
{
public:
    virtual void func()
    {
        cout<<"base::func()----------\r\n";
    }
};

class sub:public base
{
public:
    void test()
    {
        cout<<"sub::test()-------------\r\n";
    }
};

int main()
{
    base obj1;
    sub obj2;
    base *p=&obj1;
    sub *q=&obj2;
    //A pointer to a base class is converted to a pointer to a derived class
    sub *q2=static_cast<sub *>(p);
    sub *q3=dynamic_cast<sub *>(p);
    //q2->func();
    q2->test();

    //The pointer of the derived class is converted to the pointer of the base class
    base *p2=static_cast<base *>(q);
    p2->func();

    sub *p3=dynamic_cast<sub *>(q);
    p3->func();

    return 0;
}

​


4 smart pointer -- "represents a scope


Essence: make the life cycle of the smart pointer consistent with the life cycle of the heap memory. When the smart pointer is released, the heap memory space is automatically released

Why use smart pointers? C + + has no automatic memory recovery mechanism. When we write a new statement, we usually write the delete statement directly, but we can't avoid jumping before the program executes the delete statement or the program returns before the function executes the delete statement, which will cause memory leakage. Therefore, in order to avoid memory leakage, the smart pointer is introduced, because the smart pointer is a class scope. When it exceeds the scope of the class, the system will automatically call the destructor to release memory resources.
c + + provides four common smart pointers (class templates) -- Belong to STL
auto_ptr: automatic smart pointer (obsolete)
shared_ptr: shared smart pointer, which allows multiple smart pointers to point to the same memory space, and automatically releases the heap memory space (the space is released when the last p is gone)
weak_ptr: weak smart pointer. It cannot exist alone. It must be used together with shared smart pointer (dependent smart pointer). The increase and death of weak smart pointer will not affect the release of heap memory

#include <iostream>
#include <memory>

using namespace std;

class demo
{
public:
    demo()
    {
        cout<<"demo()----------\r\n";
    }
    ~demo()
    {
        cout"~demo()------------\r\n";
    }
};

int main()
{
    shared_ptr<demo> p(new demo);//Shared smart pointer
    shared_ptr<demo> q=p;
    cout<<q.use_count()<<endl;//Two smart pointers point to the memory space instantiated by demo
    
    p.reset();//Release p
    cout<<q.use_count()<<endl;//There is a smart pointer to the memory space instantiated by the demo
    weak_ptr<demo> r=q;//Dependent smart pointer
    q.reset();//Release q
    if(r.expired())
    {
        cout<<"Heap space freed\r\n";
    }
    else
    {
        cout<<"Heap space not released\r\n";
    }
    
    return 0;
}


unique_ptr: exclusive pointer. Only one exclusive smart pointer can point to a piece of memory at a time.  
    

#include <iostream>
#include <memory>

using namespace std;

class demo
{
public:
    demo()
    {
        cout<<"demo()--------\r\n";
    }
    ~demo()
    {
        cout<<"~demo()--------\r\n";
    }
    void func()
    {
        cout<<"demo::func()-------\r\n";
    }
};

int main()
{
    unique_ptr<demo> p(new demo);
    p->func();
    
    return 0;
}


reset(): free the space requested by new
expired(): check whether the new space has been released. If so, return true; If not released, return to false.

Topics: C++