• C语言进阶C++知识点补充(一)


    C语言进阶到C++知识点补充

    1、思想:由于C语言的面向过程进阶到C++的面向对象。

    2、新特性:C++实现封装、继承、多态

    3、新知识点:类和对象、继承、重载、多态、数据封装、异常处理、模板

    1、引用

    阅读本节你将掌握的知识点

    C++引用
    引用变量是一个别名。他是某个已经存在的变量的另外一个名字。
    一旦把引用初始化为某个变量,就可以使用该引用名称或者变量名称来指向变量。

    C++引用和指针
    三个不同点:
    1)不存在空引用,引用必需连接到一个合法内存
    2)一旦引用被初始化一个对象,就不能被指到另外一个对象,指针可以再任何时候指向到另一个对象
    3)引用必须在创建的时候被初始化,指针可以在任何时候进行初始化。

       int i = 17;
    
       int & r = i;
       
       double & s = d;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    引用的使用场景
    1、引用作为函数的参数列表
    引用作为参数传给函数,这比传一般的参数更加安全

    2、引用作为返回值
    可以从C++函数中返回引用,就像返回其他数据类型一样通过用引用来替代指针,使得C++程序更容易维护,C++返回一个引用,方式与返回一个指针类似、当函数返回一个引用的时候,则会返回一个指向返回值的隐式指针,这样,函数就可以放在赋值语句的左边。

    #include 
    #include 
    #include 
    using namespace std;
    
    
    //引用传参
    void swap(int &x,int &y)
    {
        int temp;
        temp = x;
        x = y;
        y = temp;
    }
    
    //把引用作为返回值
    double vals[] = {10.1,12.6,33.1,24.1,50.0};
    
    double &setValues(int i){
        double &ref = vals[i];
        return ref; //返回第一个元素的引用,ref是一个引用变量,ref引用vals[i]
    }
    
    //当返回一个引用的时候,注意对象不能超过作用域,返回一个局部变量的引用是不合法的,但是可以返回一个静态变量的引用。
    
    int &func(){
        int q;
        //! return q; //在编译时发生错误
        static int x;
        return x;
    
    }
    
    
    int main(int argc, char **argv)
    {
        cout <<"改变之前的值"<<endl;
        for (int i = 0; i < 5; i++)
        {
            cout<<"vals["<<i<<"]"<<vals[i]<<endl;
        }
    
        setValues(1) = 20.23;//改变第二个元素
        setValues(3) = 70.8; //改变第四个元素
    
        cout <<"改变之后的值"<<endl;
        for (int i = 0; i < 5; i++)
        {
            cout<<"vals["<<i<<"]"<<vals[i]<<endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    2、类和对象

    阅读本节你将掌握的知识点
    1、面向对象的编程思想
    新定义类的都以class类为蓝本。
    2、类的定义、类中的成员和方法

    3、构造函数和析构函数

    4、友元函数

    5、拷贝构造函数
    是一种特殊的构造函数,它在创建对象时,使用同一个类中之前创建的对象来初始化新创建的对象。拷贝构造函数常用于:
    1、通过使用另外一个同类型的对象初始化新创建的对象
    2、复制对象把它作为参数传递给函数
    3、复制对象,并从函数返回这个对象
    如果类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。
    拷贝构造函数的常用格式如下:
    classname (const classname &obj){
    //构造函数的主体
    }
    6、this指针 && 指向类成员的指针
    每个对象都可通过this指针来访问自己的地址,this是所有成员函数的隐含参数,因此在成员函数的内部,可以用来调用对象。
    友元函数没有this指针,因为友元函数没不是类的成员,只有成员函数才有this指针。

    7、访问权限 三类
    1)public成员类外可以直接访问
    2)private成员类外无法直接访问,如赋值、初始化等操作,需要借助函数类外实现
    3)protect成员类外无法直接访问,不过可以通过子类继承来访问父类成员。
    私有成员和保护成员不能直接用成员运算符访问!!!

    #include
    using namespace std;
    
    class box
    {
    public:
        double length;//成员
        double height;
        double width;
    
        double get(void);//方法
        void set(double len,double wid,double height);
    
        friend int getboxlength(box box);//友元函数:可以访问在类外访问类内成员
    
        bool compare(box boxx);
    
        int getlength();
    
    private:
        int *ptr;
    
    public:
        box(){
            cout<<"none arguments"<<endl;
        }
        box(int len){ //构造函数
           
            ptr = new int;
            *ptr = len;
        }
        box(const box &obj); //拷贝构造函数
    
        ~box(){ //析构函数
            cout<<"release mem"<<endl;
            delete ptr;
        }
    };
    
    //this指针的示例
    bool box::compare(box boxx)
    {
        if (this->length>boxx.length)
        {
            cout<<"go"<<endl;
            return true;
        }
        else return false;
    }
    
    int box::getlength(){
        return *ptr;
    }
    
    //拷贝构造函数
    box::box(const box &obj)
    {
        cout<<"拷贝构造函数的调用"<<endl;
        ptr = new int;
        *ptr = *obj.ptr;//拷贝的数值
    }
    
    void dispaly(box obj){
        cout<<"获得的长度为:"<<obj.getlength()<<endl;    
    }
    
    //友元函数
    int getboxlength(box box)
    {
        return box.length;
    }
    
    double box::get(void)
    {
        return length*width*height;
    }
    
    void box::set(double len,double wid,double hei)
    {
        length = len;
        width = wid;
        height = hei;
    }
    
    int main(){
    
        box box1(10);
    
        box box2 = box1;
        box1.length = 3;
        box1.height = 4;
        box1.width  = 5;
    
        box2.length = 1;
       
        box1.compare(box2);
    
        box *ptr;
    
        ptr = &box1;
    
        cout<<"ptr->length = "<<ptr->height<<endl;
        double value = 0.0;
    
        //cout<<"友元函数的使用:"<
    
        return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108

    3、继承

    阅读本节你将掌握的知识点
    1、类的继承
    public、private、protected
    访问控制和继承:
    派生类可以访问基类中的所有非私有成员,因此,基类成员如果不想被派生类的成员函数访问,应该在基类中声明为private。protected类可以在派生类中被访问。
    访问权限的类型总结:

               public      protected       private
    同一个类        y           y               y
    派生的类        y           y               n
    外部的类        y           n               n
    
    • 1
    • 2
    • 3
    • 4

    一个派生类继承了所有的基类的方法,但是如下情况除外:

    1)基类的构造函数、析构函数、拷贝构造函数

    2)基类的重载运算符

    3)基类的友元函数

    通常还是使用 public继承方式

    2、多继承 一个子类可以有多个父类,它继承了多个父类的特性。
    class <派生类名称>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
    {
    <派生类类体>
    }

    #include
    using namespace std;
    
    //基类1
    class base{
        public:
            void setwidth(int wid);
            void setlength(int len);
        protected:
            int length;
            int width;
    };
    
    void base::setlength(int len)
    {
        length = len;
    }
    
    void base::setwidth(int wid)
    {
        width = wid;
    }
    
    //基类2
    class CalcCost{
        public:
            int getCost(int area)
            {
                return area*70;
            }
    };
    
    //派生类
    class CalcArea:public CalcCost,public base{
    
        public:
            int getArea()
            {
                return length * width;
            }
    };
    
    int main(){
    
        CalcArea Rect;
        
        int area;
    
        Rect.setlength(5);
        
        Rect.setwidth(7);
    
        area = Rect.getArea();
        //输出面积
        cout<<"面积为:"<<Rect.getArea()<<endl;
        //输出花费
        cout<<"总花费为:"<<Rect.getCost(area)<<endl;
        return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    4、重载运算符和重载函数

    阅读本节你将掌握的知识点

    1、运算符重载的实现

    2、运算符重载的列表

    3、可重载运算符和不可重载运算符
    重点记忆不可重载的运算符:

       .:成员访问运算符
       .* ->* 成员指针访问运算符
       :: : 域运算符
       sizeof : 长度运算符
       ?  条件运算符
       # 预处理运算符
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4、重载函数的实现是函数名相同,函数内的参数不同,代码被编译执行后,编译器会自动找到对应的重载函数。

    
    #include
    using namespace std;
    class Box
    {
        public:
            double getValue(void){
                return length*breadth*height;
            }
    
            void setLength(double len)
            {
                length=len;
            }
    
            void setBreadth(double bre)
            {
                breadth=bre;
            }
    
            void setHeight(double hei)
            {
                height = hei;
            }
    
            //重载运算符 括号中的是右值,双目运算符的重载
            
            Box operator+(const Box& b)
            {
                Box box;
                box.length = this->length+ b.length;
                box.height = this->height+ b.height;
                box.breadth = this->breadth+ b.breadth;
                return box;
            }
    
        private:
            double length;
            double height;
            double breadth;
    
    };
    
    
    
    int main(){
        Box box1;
        Box box2;
        Box box3;
    
        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.getValue();
        cout<<"volume of box1 : "<<volume<<endl;
    
        //box2
        volume = box2.getValue();
        cout<<"volume of box2 : "<<volume<<endl;
    
        //box3:两个对象相加得到BOX3
        box3 = box2 + box1;
    
        volume  = box3.getValue();
    
        cout<<"volume of box3 : "<<volume<<endl;
    
        return 0; 
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    5、多态

    阅读本节你将掌握的知识点
    1、多态:类之间存在层次结构,并且类之间是通过继承关联的时候,就会用到多态,
    C++多态意味着调用成员函数的时候,会根据调用成员函数的对象的类型不同来执行不同的操作。

    2、关键字virtual的使用。
    1)虚函数 是基类中使用virtual声明的函数。
    在派生类中重新定义基类中定义的虚函数时,告诉编译器不要静态链接到该函数。

    需要让程序再任一点可以根据所调用的对象类型来选择调用的函数,这种操作称之为动态链接或者后期绑定。

    2)纯虚函数:想在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是又不能在虚函数中给出有意义的实现。

    虚函数和纯虚函数:虚函数在基类中已经实现了方法, 但是派生类不调用,纯虚函数时基类中没有实现方法,派生类自主实现方法。

    #include
    using namespace std;
    
    class Shape{
        protected:
            int width, height;
        public:
            Shape(int a = 0,int b = 0)
            {
                width = a;
                height = b;
            }
            //基类中使用virtual 关键字
            virtual 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; 
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
  • 相关阅读:
    还在每天玩单调的控制台窗口?赶紧进来!!!用EasyX画出自己的优美窗口(万字教程,一文入门)
    SMART S7-200PLC串行自由口通讯(耐压测试仪)
    链表经典面试题之一讲
    Shell之练习一
    uniapp+unocss报错Error [ERR_REQUIRE_ESM]: require() of ES Module
    【ClickHouse 进阶笔记】
    341.扁平化嵌套列表迭代器 | N叉树的最大深度
    Python中stack和unstack函数(附加reset_index,set_index函数)
    pdf文档打不开是怎么回事?
    matlab读取hdf5格式的全球火灾排放数据库Global Fire Emissions Database(GFED)数据
  • 原文地址:https://blog.csdn.net/m0_46152793/article/details/125884863