• c++03封装


    C++封装

    封装:把一些信息封装起来,只暴露出用户关心的信息。通过访问限定符将想要暴露的暴露出来,想要隐藏的隐藏起来。

    类和对象

    对象实例化:

    从栈中实例化:类的名字,对象名字

    从堆中实例化:用new申请一块内存,用指针指向这快内存的地址。申请使用完之后要将内存释放置空掉(delete 指针 、指针=NULL)。

    从栈上和从对上访问成员函数的方法:(左图上从栈上,右图是从堆上)

    image-20201107160143577

    栈:

    #include<iostream>` `using namespace std;` `class Coordinate{` `public:` `int x;` `int y;` `void printX(){` `cout<<x<<endl;` `}` `void printY(){` `cout<<y<<endl;` `}` `};` `int main(){` `Coordinate c;` `c.x=10;` `c.y=20;` `c.printX();` `c.printY();` `return 0;` `}

    堆:

    #include<iostream>
    using namespace std;
    class Coordinate{
    public:
    int x;
    int y;
    void printX(){
    cout<<x<<endl;
    }
    void printY(){
    cout<<y<<endl;
    }
    };
    int main(){
    ``Coordinate *p=new Coordinate(); if(NULL==p){ return 0; } p->x=100; p->y=200; p->printX(); p->printY(); delete p; p=NULL; return 0; }`

    数据成员和成员函数

    数据成员也叫属性。

    成员函数也叫方法。

    字符串类型

    与java不同的是使用字符串需要引入string头文件;string首字母小写;字符串用双引号,字符使用单引号。

    1、string s1;此时s1是一个空串。

    2、string s2="wangjiaer";赋初始值。

    3、string s3(s2);s3是s2的一个副本。

    4、strings4(n,'c');s4初始化为字符‘c’的n个副本。

    5、string的常用操作:

    image-20201107162917568

    非法写法:string s=“hello”+“world”;

    练习:

    #include <iostream>
    #include <string>
    using namespace std;
    /**
      * 定义类:Student
      * 数据成员:名字、年龄
        */
        class Student
        {
        public:
        // 定义数据成员名字 m_strName 和年龄 m_iAge
        string m_strName;
        int m_iAge;
        };
    int main()
    {
        // 实例化一个Student对象stu
        Student stu;
        // 设置对象的数据成员
        stu.m_strName = "慕课网";
        stu.m_iAge = 2;  
    // 通过cout打印stu对象的数据成员
    cout << m_strName << " " << m_iAge<< endl;
    return 0;
    }
    

    报错:倒数第三行m_strName 和 m_iAge没有定义。

    原因:在main函数中我声明定义的``stu.m_strName = "慕课网"; stu.m_iAge = 2; 这个是对象stu的定义。而m_strName 和 m_iAge是没有定义的。按照要求 // 通过cout打印stu对象的数据成员
    ,正确写法是:

    cout << stu.m_strName << " " << stu.m_iAge<< endl;

    属性封装

    面向对象的基本思想:对象在程序中的所有操作都转换成对函数的操作。

    get/set方法:对私有属性进行操作。

    练习:

    include

    include

    using namespace std;

    /**

    • 定义类:Student
    • 数据成员:m_strName
    • 数据成员的封装函数:setName()、getName()
      */
      class Student
      {
      public:
      // 定义数据成员封装函数setName()
      void setName(string _name){
      m_strName=_name;

      }
      // 定义数据成员封装函数getName()
      string getName(){
      return m_strName;
      }
      //定义Student类私有数据成员m_strName
      private:
      string m_strName;
      };

    int main()
    {
    // 使用new关键字,实例化对象
    Student *str = new Student();
    // 设置对象的数据成员
    str->setName("慕课网");
    // 使用cout打印对象str的数据成员
    cout<getName();
    // 将对象str的内存释放,并将其置空
    delete str;
    str=NULL;
    return 0;
    }

    类内定义和内联函数

    内联函数:inline;

    类内定义:函数和函数体写在类的内部。

    类内定义的成员函数,编译器会优先将其编译为inline函数。

    类外定义:同文件类外定义,分文件类外定义

    同文件类外定义:成员函数的定义在类外定义,但是需要声明是哪个类的方法。

    分文件类外定义:将成员函数的声明写在一个与类名相同的头文件中(类名.h),在类中需要将该头文件引入,才可以定义头文件中的方法。

    构造函数和析构函数

    image-20201109165357020

    对象初始化:有且仅有一次或者根据条件初始化。

    构造函数:初始化。在对象实例化时被自动调用。构造函数在初始化实例对象被调用且仅被调用一次。构造函数与类同名,没有返回值,可有多个重载形式,但是在实例化对象时候,只会用到一个构造函数。用户如果没有定义构造函数,编译器会自动生成一个构造函数。

    在实例化对象时不需要传递参数的叫做默认构造函数。无参构造函数默认构造函数。

    拷贝构造函数:

    image-20201109200222345

    拷贝构造函数的参数是确定的,不能重载

    析构函数

    格式:~类名()

    析构函数没有参数,不能被重载.

    image-20201109200845924

    image-20201109200951058

    练习:

    #include <iostream>
    #include <string>
    using namespace std;
    /**
     * 定义类:Student
     * 数据成员:m_strName
     * 无参构造函数:Student()
     * 有参构造函数:Student(string _name)
     * 拷贝构造函数:Student(const Student& stu)
     * 析构函数:~Student()
     * 数据成员函数:setName(string _name)、getName()
       */
    class Student{
        public:
            Student(){
            };
            Student(string _name){
                 _name=m_strName;
            }
            Student(const Student& stu){
        }
        ~Student(){
            
        }
        void setName(string  _name){
           m_strName=_name;
        }
        string getName(){
            return m_strName;
        }
    private:
        string m_strName;
        }; 
    int main(void)
    {
        // 通过new方式实例化对象*stu
        Student *stu = new Student();
        // 更改对象的数据成员为“慕课网”
    	stu->setName("慕课网");
        // 打印对象的数据成员
    	cout<<stu->getName();
    	return 0;
    }
    

    上面之前一直没有输出的原因是,我定义Set方法的时候,写成了:

    void setName(string name){
    name=m_strName
    ;
    }

    这是典型的错误.

    正确应该是上面完整代码那样:

    void setName(string _name){
    m_strName=_name; //赋值语句
    }

    对象指针

    对象指针:用一个指针指向对象。p->x=10;(*p).x=10;

    类名 *p2=&p1;用p2的指针指向p1的地址。

    this指针

    如果参数和数据成员同名,编译器无法分辨。

    this指针就是指向对象自身数据的指针。所以如果重名,用this指针就行。

    image-20201113172723093

    每次调用成员函数都使用到了this指针。

    this指针就是指向所在对象的地址。

    对象数组

    堆中实例化的数组需要手动销毁释放内存,在栈中实例化的数组,系统自动回收内存。

    对象成员

    存在的问题:

    ===================Coordinate.h

    class Coordinate{
    public:
    Coordinate();
    ~Coordinate();
    void setX(int x);
    int getX();
    void setY(int y);
    int getY();
    private:
    int m_iX;
    int m_iY;
    };

    ======================Line.h

    include "Coordinate.h"

    class Line{
    public:
    Line();
    ~Line();
    void setA(int x,int y);
    void setB(int x,int y);
    void printInfo();
    private:
    Coordinate m_coorA;
    Coordinate m_coorB;
    };

    =====================Coordinate.cpp

    include"Coordinate.h"

    include

    Coordinate::Coordinate(){
    cout<<"coor()";
    }
    Coordinate::~Coordinate(){
    cout<<"~coor()";
    }
    void Coordinate::setX(int x){
    m_iX=x;
    }
    int Coordinate::getX(){
    return m_iX;
    }
    void Coordinate::setY(int y){
    m_iY=y;
    }
    int Coordinate::getY(){
    return y;
    }

    ========================Line.cpp

    include"Line.h"

    include

    Line::Line(){
    cout<<"line()";
    }
    Line::~Line(){
    cout<<"~line()";
    }
    void Line::setA(int x,int y){
    m_coorA.setX(x);
    m_coorA.setY(y);
    }
    void Line::setB(int x,int y){
    m_coorB.setX(x);
    m_coorB.setY(y);
    }
    void Line::printInfo(){
    cout<<m_coorA.getX()<<m_coorA.getY();
    cout<<m_coorB.getX()<<m_coorB.getY();

    }

    ===========================demo.cpp

    include

    include "Line.h"

    using namespace std;
    int main(){
    Line *p=new Line();
    delete p;
    p=NULL;
    return 0;
    }

    报错:

    image-20201111213830337

    拷贝构造函数

    浅拷贝:将值直接拷贝过去。这样会导致两个值指向的地址是用一个地址,导致释放内存的时候会出现释放两次,一定出问题。

    深拷贝:为了解决上面的问题。在拷贝构造函数中,给要复制的对象申请内存。将传入的对象对应位置的内存拷贝到申请的内存中。

    对象成员指针

    一个指针在32为编译器下指向4个内存单元。

    对象需要看他包含几个指针。

    const

    常对象成员和常成员函数

    image-20201113210456449

    由const修饰的对象成员和成员函数。

    image-20201113211130033

    互为重载:常成员函数和成员函数。调用名字相同的常成员函数时候需要在前面加上const。

    image-20201113211332588

    常指针与常引用

    image-20201113213037529

    image-20201113213055630

    没有const修饰的时候要求读写权限。

    迷宫--算法

    左手规则,右手规则。

    (出口和入口不是同一个口)

    迷宫类:二维 数组 0-墙/1-路

    人类:人;人的朝向;当前位置;人前一个位置;人的速度;

    ​ 构造函数,封装函数,朝不同方向前进的函数;开始函数;转弯函数。

    image-20201113215601724

  • 相关阅读:
    「模板」 树套树
    [Luogu 3701] 「伪模板」主席树
    「模板」 可持久化平衡树
    「模板」 割点
    [Luogu 2596] ZJOI2006 书架
    省选有感。(不是游记)
    [Luogu 2604] ZJOI2010 网络扩容
    MySql聚簇索引与非聚簇索引的区别
    四层负载均衡和七层负载均衡的区别
    Redis利用Pipeline加速查询速度的方法
  • 原文地址:https://www.cnblogs.com/yunxiaoqian/p/13986908.html
Copyright © 2020-2023  润新知