C++ 面向对象编程1

概念


  一切都可以是对象,一个程序可以由一组对象组成的一组整体,程序的功能就是通过对象之间传递消息来实现的。如上图所示,比如有一个人在家里,需要坐飞机到达某一个地方,那他需要经历的步骤可能为,走到公交站--》坐公交车到地铁站-》坐地铁到机场--》坐飞机到达目的地。
  如果使用面向过程的编程方法就是将每一个步骤写成一个函数实现,按照顺序调用;
  如果使用面向对象来实现上面的动作,则在实现动作之前需要将对象先创建出来,抽取当前情形下所感兴趣的特征,可以是变量或函数(功能),在当前情景下人需要走的功能,汽车和地铁需要载客的功能等,将这些功能组合起来便可以实现出当前情景下的动作。

如何描述对象类型

1.使用结构体(struct)描述

  C++对结构体语法进行了扩展,结构体中既可以有成员变量,也可以有成员函数。因此结构体就可以用来描述对象的类型,在C++中,对象的类型叫类。可以看出其实C语言也可以实现,成员函数可以用函数指针来代替。
实验程序
  实现一个时间类提供一个走秒的函数run(调用一次时间+1秒),在主函数中调用该函数实现时间的走动。

#include <iostream>
#include <unistd.h>
#include <iomanip>

using namespace std;

struct Time{  //创建类
    int r_hours;
    int r_minute;
    int r_second;

    //设置当前时间的函数
    void  set_time(int hours = 23, int minute = 59, int second = 55)
    {
        r_hours = hours;
        r_minute = minute;
        r_second = second;
    }
    //打印当前时间的函数
    void  show_time()
    {
        //setw(2)表示输出的字符宽度为2,不足的部分用字符'0'填充
        cout<<setw(2)<<setfill('0')<<r_hours<<":"<<setw(2)<<setfill('0')<<r_minute<<":"<<setw(2)<<setfill('0')<<r_second<<endl;
    }
    //走秒的函数
    void run_time()
    {
        r_second++;
        if (r_second==60)
        {
            r_second = 0;
            r_minute++;
            if (r_minute==60)
            {
                r_minute = 0;
                r_hours++;
                if (r_hours==24)
                {
                    r_hours = 0;
                }
            }
        }
    }
};

int main()
{
    Time time;//创建一个对象
    time.set_time();

    while(1)
    {
        time.show_time();
        sleep(1);
        time.run_time();
    }
}

输出结果:

2.使用class类来描述对象的类型

  不过大部分情况下不会使用struct来实现面向对象的编程,而是使用class,其用法和struct几乎一样,只是类中的成员具有访问属性,访问属性分为三种:

访问属性 public --- 公有属性 protected --- 保护属性 private --- 私有属性
特点 可以在类的内部和外部访问 可以在类内和子类中访问 只能在类内访问
  类成员的访问属性就是实现封装的基础,封装就是内部私有的数据隐藏,对外的接口公开。struct声明的类中的成员默认是公开的,class声明的类中的成员默认是私有的,如果类外需要访问私有的成员变量就通过成员函数来访问。一般都需要手动指定成员的访问属性:
class 类名{
public:
    公有成员;
protected:
    受保护成员;
private:
    私有成员;       
};

构造函数

1.概念

  在创建一个对象的时候,可能会需要将其中成员进行初始化的情况这可以使用构造函数,构造函数会在类构造对象时自动调用一次,其作用就是初始化对象,处于类内部,它是一个特殊的函数,它必须和类同名,而且没有返回值,其访问属性必须时公开的。

2.对象的构造过程

  a.根据对象的大小分配空间(为成员变量分配)
  b.检查成员变量的类型,基本类型则什么都不做,类类型就调用该类的构造函数
  c.调用对象对应类的构造函数

3.构造函数的重载

  一个类可以有多个构造函数,这些构造函数构成重载关系,构造对象可以传参数,传参数的方法就是在对象名后加小括号,小括号写上构造函数的实参。注意:构造函数可以有默认值,但是不要和重载发生冲突。

4.初始化参数列表

  当类中的成员有引用或const时,需要在调用构造函数之前将它们进行初始化,在构造函数的参数之后,函数语句体之前,使用初始化参数列表 来实现在调用构造函数之前对成员初始化,语法如下:

class A{
public:
    A():/*初始化参数列表*/{
        //.....
    }    
};

//初始化参数列表
构造函数名(形参列表):初始化成员1(值1),初始化成员2(值2),......{
    函数语句体
}

5.this指针

  this指针用在类内部的成员函数和构造函数中,代表的是调用该函数的对象/构造的对象。
  this指针的用法:
    a.可以在成员函数和构造函数中,使用this指针对重名的函数形参和成员变量做区分;
    b.this作为函数参数和返回值。
实验程序

#include <iostream>

using namespace std;

class A{
public:
    //构造函数
    A(){cout<<"A()"<<endl;}
};

class students{
public:
    //构造函数
    students(int age, int weight, int& m_num, int m_height):height(m_height),num(m_num)
    {
        cout<<"students(int&,int)"<<endl;
        age = 10;   //根据就近原则这个代表的是局部变量age
        this->age = 15; //当需要使用成员的age时,需要加上this指针,因为重名了
        weight = 5.5;
        this->weight = 6.0;
        name = "xiaofei";
    }

    //构造函数的重载
    students(int m_age, int& m_num, int m_height, float m_weight=4.3f,string m_name="xiaohua"):height(m_height),num(m_num)
    {
        cout<<"students(int,int&,int,float,string)"<<endl;
        age = m_age;
        weight = m_weight;
        name = m_name;
    }

    //成员函数
    students *show()
    {
        //哪个对象调用函数show(),this就代表谁
        cout<<this->name<<":"<<this->age<<":"<<this->num<<":"<<this->height<<":"<<this->weight<<endl; 
        return this;
    }
    void run()
    {
        cout<<this->name<<":run...."<<endl;
    }

private:
    int age;
    string name;//C++提供的字符串类
    float weight;  
    const int height;
    int& num;
    A a;  
};

int main()
{
    int num = 10;
    int height = 130;
    students xiaohua(8, num, 120, 50);
    xiaohua.show();
    students xiaofei(10, 60, num, height);
    xiaofei.show()->show()->show()->run(); //程序show()函数会返回响应对象的指针,可以用这个指针继续访问其中成员

    return 0;
}

输出结果

总结

  1.类中的成员一般公开的写前面,私有的写最后;
  2.如果类没有构造函数,编译器会在编译时自动生成一个,改函数什么也不做,如果类有构造函数,编译器就不会坐这个工作;
  3.类中函数访问成员变量时,尽量使用this指针,避免出现歧义;
  4.类的前置声明:声明一个类名,类中的具体信息在之后的代码中定义,当使用类时,类还没有实现可以使用类的前置声明:

class 类名;//前置声明
posted @ 2021-03-14 17:08  ding-ding-light  阅读(70)  评论(0编辑  收藏  举报