C++ class related operations

C++ class operations related

class constructor

  • The constructor has the same name as the class and has no return value. The parameter list can pass in multiple sets of parameters, that is, the constructor is not unique. The following is the initialization member list, that is, it can be initialized by using parentheses after the colon.
  • Note: When defining a class, when using the = sign, instead of assigning ( assignment), the constructor ( constructor) function is called
  • MyClass001.h

    #ifndef MYCLASS001_H
    #define MYCLASS001_H
    
    #include <stdio.h>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include <set>
    #include <string.h>
    #include <map>
    #include <unordered_map>
    #include <unordered_set>
    #include <iostream>
    #include <queue>
    #include <list>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    using namespace std;
    
    class Myclass001
    {
    public:
        Myclass001(int a = 0, int b = 0, int c = 0)
            : _a(a), _b(b), _c(c)  // 相当于将a赋值给_a,以此类推
        {
            cout << "a : " << _a << ", b :" << _b << ", c : " << _c << endl;
        }
    
    private:
        int _a;
        int _b;
        int _c;
    };
    
    #endif
    
  • main.cpp

    #include <stdio.h>
    #include "MyClass001.h"
    using namespace std;
    typedef long long ll;
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        // 4种初始化方式
        Myclass001 mc1; // 如果参数列表为空,则不用加括号,表示不带参数的构造函数
        Myclass001 mc2(2);
        Myclass001 mc3(2,3);
        Myclass001 mc4(2, 3, 4);
    
        // 这里即使是=的符号,也是构造函数,相当于传入一个参数进行构造
        Myclass001 mc5 = 5; 
    
        system("pause");
        return 0;
    }
    

destructor

  • When applying for resources such as memory space in a class, you need to release these memory spaces in the destructor when the life of the class ends.

  • MyClass02.h

    #ifndef MyCLASS002_H
    #define MyCLASS002_H
    
    #include <stdio.h>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include <set>
    #include <string.h>
    #include <map>
    #include <unordered_map>
    #include <unordered_set>
    #include <iostream>
    #include <queue>
    #include <list>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    using namespace std;
    
    class MyClass002
    {
    public:
        MyClass002(int row, int col)
            : _row(row), _col(col)
        {
            cout << "apply for memory" << endl;
            pmat = new double[ _row * _col ];
        }
    
        ~MyClass002()
        {
            cout << "free memory" << endl;
            delete []pmat;
        }
    
    private:
        int _row, _col;
        double *pmat;
    };
    
    #endif
    
  • main.cpp

    #include <stdio.h>
    #include "MyClass002.h"
    using namespace std;
    typedef long long ll;
    
    // 在函数中测试,可以看到调用析构函数时的状态
    void testClass()
    {
        MyClass002 mc(3, 4);
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

Class members are initialized one by one

  • For the general so-called situation, when B=A is directly assigned between classes, the elements in A will be copied to B one by one, which is no problem for some commonly used simple types of data, but if the class contains variables such as addresses , this copying will cause a big problem: two classes will share the same memory space, if one class is destructed and this memory space is released, it is very dangerous to continue to use it in another class things, so for some classes, you need to write a separate copy constructor,
  • The following first gives a wrong code example
  • Class002.h

    #ifndef MyClass002_H
    #define MyClass002_H
    
    #include <stdio.h>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include <set>
    #include <string.h>
    #include <map>
    #include <unordered_map>
    #include <unordered_set>
    #include <iostream>
    #include <queue>
    #include <list>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    using namespace std;
    
    class MyClass002
    {
    public:
        MyClass002(int row, int col)
            : _row(row), _col(col)
        {
            cout << "apply for memory" << endl;
            pmat = new double[ _row * _col ];
        }
    
        ~MyClass002()
        {
            cout << "free memory" << endl;
            delete[]pmat;
            pmat == NULL;
    
        }
    
        bool SetValue(int r, int c, int val)
        {
            if (r < 0 || r > _row || c < 0 || c > _col)
                return false;
            pmat[r*_col+c] = val;
            return true;
        }
    
        int getValue(int r, int c)
        {
            if (r < 0 || r > _row || c < 0 || c > _col)
                return  INT_MIN;
            return pmat[r*_col + c];
        }
    
    private:
        int _row, _col;
        double *pmat;
    };
    
    #endif
    
  • main.cpp

    #include <stdio.h>
    #include "MyClass002.h"
    using namespace std;
    typedef long long ll;
    
    // 这个程序无法结束,因为系统在已经释放掉的资源时出现问题,而且修改了mc1中的内容后,mc2中的变量也被修改,不符合设计要求
    void testClass()
    {
        MyClass002 mc1(3, 4);
    
        MyClass002 mc2 = mc1;
    
        mc1.SetValue( 0,0,10 );
        cout << mc2.getValue(0, 0) << endl;
    
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    
  • When doing copy constructor, you can access the private member variables of the class within the function. The correct way to write the copy constructor is given below.

  • MyClass002.h

    #ifndef MYCLASS002_H
    #define MYCLASS002_H
    
    #include <stdio.h>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include <set>
    #include <string.h>
    #include <map>
    #include <unordered_map>
    #include <unordered_set>
    #include <iostream>
    #include <queue>
    #include <list>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    using namespace std;
    
    class MyClass002
    {
    public:
        MyClass002(int row, int col)
            : _row(row), _col(col)
        {
            cout << "apply for memory" << endl;
            pmat = new double[ _row * _col ];
        }
    
        // 在类中,该类的实例可以访问对应的private变量
        MyClass002(const MyClass002& mc)
            : _row(mc._row), _col(mc._col)
        {
            cout << "copy constyructor" << endl;
            int cnt = _row * _col;
            pmat = new double[cnt];
            for (int i = 0; i < cnt; i++)
                pmat[i] = mc.pmat[i];
        }
    
        ~MyClass002()
        {
            cout << "free memory" << endl;
            delete[]pmat;
            pmat == NULL;
    
        }
    
        bool SetValue(int r, int c, int val)
        {
            if (r < 0 || r > _row || c < 0 || c > _col)
                return false;
            pmat[r*_col+c] = val;
            return true;
        }
    
        int getValue(int r, int c)
        {
            if (r < 0 || r > _row || c < 0 || c > _col)
                return  INT_MIN;
            return pmat[r*_col + c];
        }
    
    private:
        int _row, _col;
        double *pmat;
    };
    
    #endif
    
  • main.cpp

    #include "MyClass002.h"
    using namespace std;
    typedef long long ll;
    
    void testClass()
    {
        MyClass002 mc1(3, 4);
        // 使用类的构造函数进行初始化,会重新申请内存空间
        MyClass002 mc2 = mc1;
    
        // 两块内存空间相互不干扰,程序可以正常运行
        mc2.SetValue(0,0,5 );
        mc1.SetValue( 0,0,10 );
        cout << mc2.getValue(0, 0) << endl;
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

const modified member function

  • For function parameters that cannot be modified, we can use const to limit them, but we also need to ensure that any sub-function that uses the const variable in the function does not modify it, so that the compiler knows that these functions are being called. When the value is not modified, the member function needs to be modified with const, which is equivalent to telling the compiler:这个成员函数不会修改类对象的内容
  • If the class is used as the return value (reference, etc.), and the function is const modified, you also need to ensure that the return value is limited to const
  • MyClass003.h

    #ifndef MYCLASS003_H
    #define MYCLASS003_H
    
    #include <stdio.h>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include <set>
    #include <string.h>
    #include <map>
    #include <unordered_map>
    #include <unordered_set>
    #include <iostream>
    #include <queue>
    #include <list>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    using namespace std;
    
    class MyClass003
    {
    public:
        MyClass003(int a = 0, int b = 0, int c = 0)
            : _a(a), _b(b), _c(c)  // 相当于将a赋值给_a,以此类推
        {
            //cout << "a : " << _a << ", b :" << _b << ", c : " << _c << endl;
        }
    
        // 
        int sumA(const MyClass003 &mc)
        {
            return mc.getA() + _a;
        }
    
        // 如果不加这个const,在上面调用时,会出错,因为编译器无法判断getA是否修改了类
        int getA() const
        {
            return _a;
        }
    
        // 不可以修改的引用,在这里删除前面的const会报错,因为后面的const说明不对这个类进行修改
        // 前面也需要设置为const来确保这一操作
        const int &getARef() const
        {
            return _a;
        }
    
        // 可以修改的引用
        // 重载上面的函数
        int &getARef()
        {
            return _a;
        }
    
        // 因为b被标记为mutable,因此修改其值并不会破坏整个class obj的完整性
        int &testMutable() const
        {
            _b++;
        }
    
    private:
        int _a;
        mutable int _b;
        int _c;
    };
    
    #endif
    
  • main.cpp

    #include "MyClass003.h"
    using namespace std;
    typedef long long ll;
    
    void testClass()
    {
        MyClass003 mc1(1,2,3);
        MyClass003 mc2(2,3,4);
    
        cout << mc1.sumA(mc2) << endl;
    
        int &a = mc1.getARef(); //因为a是mc1中_a的引用,因此修改a可以直接修改mc1._a
        const int &b = mc1.getARef();
        a = 2;
        cout << mc1.getARef() << endl;
    
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

this and static member variables (functions)

  • Static can be used to modify variables that have nothing to do with other class member variables or functions. When defining static member functions, non-static member functions cannot be used, but it can be used by other non-static member functions.
  • Note: static member variables and functions exist throughout the life cycle of the application
  • MyClass004.h

    #ifndef MYCLASS004_H
    #define MYCLASS004_H
    
    #include <stdio.h>
    #include <cstdlib>
    #include <iostream>
    #include <string>
    #include <set>
    #include <string.h>
    #include <map>
    #include <unordered_map>
    #include <unordered_set>
    #include <iostream>
    #include <queue>
    #include <list>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    using namespace std;
    
    class MyClass004
    {
    public:
        MyClass004(int a = 0, int b = 0, int c = 0)
            : _a(a), _b(b), _c(c)
        {
        }
    
        // this的使用,是指向当前class obj的指针
        MyClass004 copy( const MyClass004& mc )
        {
            if (this != &mc)
            {
                this->_a = mc._a;
                this->_b = mc._b;
                this->_c = mc._c;
            }
            return *this;
        }
        static int Add(const int& a, const int& b)
        {
            return a + b;
            // _a = 1; //这句话有问题,因为静态函数中不能使用非静态的函数或者成员变量
        }
    
        void printInfo()
        {
            cout << "a : " << _a << ", b :" << _b << ", c : " << _c << endl;
        }
    
    private:
        int _a;
        int _b;
        int _c;
    };
    
    #endif
    
  • main.cpp

    #include "MyClass004.h"
    using namespace std;
    typedef long long ll;
    
    void testClass()
    {
        MyClass004 mc1(1,2,3);
        MyClass004 mc2(4,5,6);
        mc2.printInfo();
        MyClass004 mc3 = mc2.copy( mc1 );
        mc2.printInfo();
        mc3.printInfo();
        cout << MyClass004::Add( 1,2 ) << endl;
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

Operator overloading and friends

  • About operator overloading

    • No new operators can be introduced, except ., *, ::, ?:other operators can be overloaded
    • The number of operands of the operator is immutable. For example, if the operator of == is 2, it must also be 2 when overloading.
    • Operator precedence cannot be changed
    • In the parameter list of the operator, there must be at least one parameter type of class type, that is, an existing operator cannot be defined for a non-class type.
    • For ++ operator overloading, in order to avoid conflicts, a parameter will be added when the suffix is ​​incremented, usually int (but this int will not be used)
  • About Friends

    • You can specify that a function is a friend of a class, this function does not need to belong to any class, or you can specify that class A is a friend of class B, so that you can use private variables and functions of class B in class A
  • MyClass005.h

    #ifndef MYCLASS005_H
    #define MYCLASS005_H
    
    #include <cstdlib>
    #include <string>
    #include <iostream>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    using namespace std;
    
    // 需要首先声明这个class的存在
    class FriendClass005;
    class MyClass005
    {
        // 指定FriendClass005为当前class的友元
        friend FriendClass005; // 声明FriendClass005是MyClass005的友元
    public:
        MyClass005(int a = 0)
            : _a(a)
        {
        }
    
        bool operator==(const MyClass005& mc) const
        {
            return mc._a == this->_a;
        }
    
        bool operator!=(const MyClass005& mc) const
        {
            return !(mc == *this);
        }
    
        // 相当于++class,前缀自增
        MyClass005 operator++()
        {
            ++_a;
            MyClass005 tmp = *this;
            return *this;
        }
    
        // 加入1个参数,防止和前面的冲突,后缀自增
        MyClass005 operator++(int)
        {
            MyClass005 tmp = *this;
            ++_a;
            return tmp;
        }
    
        void printInfo()
        {
            cout << "a : " << _a << endl;
        }
    private:
        int _a;
    };
    
    
    class FriendClass005
    {
    public:
        // 这个函数是这个类的友元,因此可以在下面定义时,直接使用其内部private变量
        friend void printClass005Info(const FriendClass005& fc);
    
        // 在MyClass005的友元中使用其private变量
        void disp(const MyClass005& mc)
        {
            cout << mc._a << endl;
        }
    private:
        int _num;
    };
    
    void printClass005Info(const FriendClass005& fc)
    {
        cout << "disp a in mc's friend class : " << fc._num << endl;
    }
    
    #endif
    
  • main.cpp

    #include "MyClass005.h"
    using namespace std;
    typedef long long ll;
    
    void testClass()
    {
        MyClass005 mc1(2);
        mc1.printInfo();
        auto mc2 = mc1++;
        mc1.printInfo();
        mc2.printInfo();
        FriendClass005 fc;
        fc.disp(mc2);
    
        cout << "===auto increase test===" << endl;
        auto mc3 = mc1++;
        auto mc4 = ++mc1;
        mc3.printInfo();
        mc4.printInfo();
    
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

function object

  • function objectRefers to function call运算符the provided class, which is used to solve lt(val)function calls such as this. lt can be a function pointer or a class boject. When it is a class object, it will convert this operation to lt.operator(val)accept function callany number of parameters.

  • MyClass006.h

    #ifndef MYCLASS006_H
    #define MYCLASS006_H
    
    #include <cstdlib>
    #include <string>
    #include <iostream>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    #include <vector>
    using namespace std;
    
    class LessThan
    {
    public:
        LessThan(int val) : _val(val)
        {
            nums = {1,2,3,4,5,6};
        }
    
        // read base value
        int compVal() const
        {
            return _val;
        }
    
        // write base value
        int compVal(int nval)
        {
            _val = nval;
        }
    
        // 实现() 的function object
        bool operator() (int val) const
        {
            return val < _val;
        }
    
        // 实现[]的function object
        int operator[] (int index) const
        {
            if (index < 0 || index >= nums.size())
                return -1;
            return nums[index];
        }
    
    private:
        int _val;
    
        vector<int> nums;
    };
    
    #endif
    
  • main.cpp

    #include "MyClass006.h"
    using namespace std;
    typedef long long ll;
    
    int countLessThan(const vector<int>& nums, int val)
    {
        int cnt = 0;
        LessThan lt(val);
        for (auto num : nums)
            if (lt(num))
                cnt++;
    
        return cnt;
    }
    
    void printLessThan(const vector<int>& nums, int val, ostream& os = cout)
    {
        int cnt = 0;
        LessThan lt(val);
        for (auto num : nums)
            if (lt(num))
                cout << num << " ";
        cout << endl;
    }
    
    void testClass()
    {
        vector<int> nums = {1,10,5,4,3,6,7,2,8,9};
        cout << countLessThan(nums, 5) << endl;
        printLessThan( nums, 5 );
        LessThan lt(0);
        cout << lt[3] << endl;
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

Overloading the iostream operator

  • Both input and output overloads need to return the corresponding iostream at the end
  • When entering, try not to set the parameter of the second class to const, because in general we need to modify it
  • Input and output overloads are not member functions, so they need to be set as friend functions, otherwise an error will occur

  • MyClass007.cpp

    #ifndef MYCLASS007_H
    #define MYCLASS007_H
    
    #include <cstdlib>
    #include <string>
    #include <iostream>
    #include <ostream>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    #include <vector>
    using namespace std;
    
    class MyClass007
    {
    public:
        MyClass007(int a = 0, int b = 0)
            :_a(a), _b(b)
        {
        }
    
        ~MyClass007()
        {
        }
    
        // 输入与输出的重载必须写成friend函数,否则编译出错,因为这个不是成员函数
        friend ostream& operator<< (ostream& os, const MyClass007& mc)
        {
            os << "MyClass007, a :" << mc._a << ", b : " << mc._b << endl;
            return os;
        }
    
        // 定义输入运算符的时候,不能将mc设置为const,否则无法通过编译(如果在其中对其修改的话)
        friend istream& operator>> (istream& is, MyClass007& mc)
        {
            is >> mc._a >> mc._b;
            return is;
        }
    
    private:
        int _a;
        int _b;
    };
    #endif
    
  • main.cpp

    #include "MyClass007.h"
    using namespace std;
    typedef long long ll;
    
    void testClass()
    {
        MyClass007 mc1(2);
        cin >> mc1;
        cout << mc1 << endl;
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

pointer to class member function

  • About the declaration and definition of class member functions and the difference from ordinary function pointers: http://www.cnblogs.com/tracylee/archive/2012/11/15/2772176.html
  • Need to use A.*bor this->.*baccess class member functions
  • When declaring the member function list, you need to add static, otherwise the problem shown in https://blog.csdn.net/cffishappy/article/details/6821222 will occur

  • MyClass008.h

    #ifndef MYCLASS008_H
    #define MYCLASS008_H
    
    #include <cstdlib>
    #include <string>
    #include <iostream>
    #include <ostream>
    #include <assert.h>
    #include <time.h>
    #include <algorithm>
    #include <functional>
    #include <iterator>
    #include <fstream>
    #include <vector>
    using namespace std;
    
    class MyClass008
    {
    public:
        MyClass008()
        {
            result.resize(3);
            _pmf = &MyClass008::square;
        }
    
        void square(int a)
        {
            result[0] = a*a;
        }
        void linearTwo(int a)
        {
            result[1] = a*2;
        }
        void minus(int a)
        {
            result[2] = -a;
        }
    
        void setType(int idx)
        {
            _pmf = func_tbs[idx];
        }
    
        void setElem(int x)
        {
            (this->*_pmf)( x );
        }
    
        void dispInfo()
        {
            for (int i = 0; i < result.size(); i++)
                cout << result[i] << " ";
            cout << endl;
        }
    
        // 使用Typedef简化类型写法
        typedef void(MyClass008::*PtrType)(int);
    
        // 声明:需要使用static修饰,否则会出现
        // https://blog.csdn.net/cffishappy/article/details/6821222
        // 中所示的问题
        static PtrType func_tbs[3];
    
    private:
        vector<int> result;
        PtrType _pmf;
    };
    
    // 
    MyClass008::PtrType MyClass008::func_tbs[3] = { &MyClass008::square, &MyClass008::linearTwo, &MyClass008::minus };
    
    #endif
    
  • main.cpp

    #include "MyClass008.h"
    using namespace std;
    typedef long long ll;
    
    void testClass()
    {
        MyClass008 mc1;
        for (int i = 0; i < 3; i++)
        {
            mc1.setType(i);
            mc1.setElem( 4 );
            mc1.dispInfo();
        }
    }
    
    int main()
    {
        // 按照时间来初始化种子,保证每次结果不一样
        srand( (int)time(0) );
        //cout << rand() << endl;
    
        testClass();
    
        system("pause");
        return 0;
    }
    

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325486067&siteId=291194637