3. C++类和对象

一、面向对象程序设计的基本特点

1.1 抽象

  • 指对具体问题(对象)进行概括,抽出一类对象的公共性质并加以描述的过程

  • 数据抽象

    • 描述某类对象的属性或状态,即此类对象与其他类对象的区别
  • 行为抽象

    • 描述某类对象的共同行为或功能特征

      以人为例,对其进行抽象。
      共同属性:姓名、性别、年龄等等,则数据抽象:

      string name, string sex, int age

      共同的行为:吃饭、走路、学习等等,则行为抽象:

      eat(), walk(), study()

1.2 C++面向对象三大特性

  1. 封装将数据和操作数据的函数代码进行有机结合,形成 “ 类 ”,其中的数据和函数都是类的成员
  2. 继承:允许在保存原有类特性的基础上,进行更具体、更详细的说明
  3. 多态:一段程序能处理多种类型对象的能力

二、类和对象的基本概念

2.1 封装

  1. 目的:

  2. 增强安全性和简化编程,使用者不需要具体了解实现细节,只需要通过外部接口,以特定的权限进行访问,使用类的成员

  3. 意义:

    1. 将属性和行为作为一个整体
    2. 将属性和行为加以权限控制
  4. 语法:

    class ClassName {
        访问权限:
            属性
            行为
    }
    

2.2 类和对象

  • 类(class)
    • 对逻辑上相关的函数和数据的封装,是对问题的抽象描述
    • 在面向对象程序设计中,程序模块是由类构成的
  • 对象(object)
    • 是具有class类型的变量
    • C++认为万事万物皆为对象对象具有属性行为
    • 具有相同性质的对象,可以抽象为类
      • 例如,人属于人类,人作为对象,属性包括姓名、性别、年龄等,行为包括吃饭、走路、学习等
      • 类中的属性和行为,统称为成员
        • 属性:成员属性,成员变量
        • 行为:成员函数,成员方法
    • 创建对象的过程叫实例化,新创建的对象叫实例(instance)

2.3 类的定义

2.3.1 语法

// 类名称通常将首字母写成大写
class 类名{
public:
    公有成员(外部接口) // 任何外部函数都可访问
private:
    私有成员		   // 只允许本类中的函数访问
protected:
    保护型成员		  // 与继承有关
}

// 实例化一个对象
类名	对象名;

// 访问数据成员
对象名.数据成员名

// 调用函数成员
对象名.函数成员名(参数表)

示例:

3. C++类和对象_第1张图片
// 封装一个圆类,求圆的面积和周长
class Circle{
public:
    // 属性:半径
    int radius;
    // 行为:获取圆面积;获取圆周长
    double findArea();
    double findPerimeter();
};

int main(){
    Circle c;
    c.radius = 10;
    
    std::cout << "圆的面积:" << c.findArea() << std::endl;
    std::cout << "圆的周长:" << c.findPerimeter() << std::endl;
}

2.3.2 成员访问权限

  • public、protected和private是访问权限修饰符
    • 被public修饰的属性和函数可以在类内部与类外部被访问
    • 被protected和private修饰的属性和函数只能在类内部被访问
  • 成员函数可以访问本类中任何成员。一般的做法是将需要被外界调用的成员函数指定为public,他们是类的对外接口
  • 有的函数并不是准备为外界调用的,而是为本类中的成员函数所调用的,就应该将它们指定为private
  • 一般将属性定义为私有,行为定义为公有
  • struct和class的区别:默认的访问权限不同
    • struct 默认权限为公共
    • class 默认权限为私有

示例:

class Clock{
public:
    void setTime(int newH, int newM, int newS);
    void showTime();
private:
    int hour, minute, second;    
}

2.3.3 类的成员函数

  • 描述类的行为,对封装的数据进行操作的方法

  • 函数的原型声明要写在类体中,函数的具体实现写在类定义外

  • 类成员函数的默认值,一定要写在类定义中

  • 语法:

    返回值类型	类名::函数成员名(参数表){
        
        函数体
    
    }
    

    示例:

    #include 
    using namespace std;
    class Clock {
    public:
        void setTime(int newH = 0, int newM = 0, int newS = 0);
        void showTime();
    private:
        int hour, minute, second;    
    };
    
    // 类成员函数setTime
    void Clock::setTime(int newH, int newM, int newS) {
        hour = newH;
        minute = newM;
        second = newS;
    }
    // 类成员函数showTime
    void Clock::showTime() {
        cout << hour << ":" << minute << ":" << second;
    }
    
    int main() {
        Clock myClock;	// 定义对象
        myClock.setTime(8, 30, 30);	// 通过“.”操作符实现对象成员函数的访问
        myClock.showTime();
        return 0;
    }
    

2.4 多文件编写代码

2.4.1 多文件结构

通常一个项目至少划分为3个文件:

  • 类定义文件(*.h文件)
    • 写类的声明,包括了所有函数的函数头
  • 类实现文件(*.cpp文件)
    • 写类的定义
    • 注意要引用类定义文件,#include *.h
    • 定义成员函数时函数名称前要加上类名:类名::函数,例如:Clock::setTime
  • 类使用文件(*.cpp,主函数文件)
    • 创建类对象并进行调用
    • 注意要引用类定义文件,#include *.h

更为复杂的程序,可以将每一个类都用单独的定义和实现文件

3. C++类和对象_第2张图片

2.4.2 例子:点和圆的关系

3. C++类和对象_第3张图片
  • 所有代码在同一个源文件内

    # include 
    using namespace std;
    
    class Point { //点类
    public:
        void setX(int x) { m_X = x; } //设置x
        int getX() { return m_X; }    //获取x
        void setY(int y) { m_Y = y; } //设置y
        int getY() { return m_Y; }    //获取y
    private:
        int m_X;
        int m_Y;       
    };
    
    class Circle { //圆类
    public: 
        void setR(int r) { m_R = r; }				        //设置半径    
        int getR(){ return m_R; }						   //获取半径    
        void setCenter(Point center){ m_Center = center; }	 //设置圆心   
        Point getCenter(){ return m_Center; } 				//获取圆心   
    private:
        int m_R;    //半径
       
        //
        //在类中可以让另一个类作为本类的成员
        //
        Point m_Center;  //圆心      
    };
    
    //判断点和圆的关系
    void isInCircle(Circle &c, Point &p){
        //计算两点之间距离平方
        int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
                       (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
        //计算半径的平方
        int rDistance = c.getR() * c.getR();
        
       //判断关系
       if(distance == rDistance){
           cout << "点在圆上" << endl; 
       }else if(distance > rDistance){
           cout << "点在圆外" << endl;
       }else{
           cout << "点在圆内" << endl;
       }               
    }
    
    int main(){
        //创建圆
        Circle c;
        c.setR(10);
        Point center;
        center.setX(10);
        center.setY(0);
        c.setCenter(center);
        //创建点
        Point p;
        p.setX(10);
        p.setY(10);
        //判断关系
        isInCircle(c, p);
    }
    
  • 多文件编写

    • 点类头文件point.h(写点类的类声明)

      # pragma once
      # include 
      using namespace std;
      
      class Point { //点类
      public:
          void setX(int x); //设置x
          int getX();       //获取x
          void setY(int y); //设置y
          int getY();       //获取y
      private:
          int m_X;
          int m_Y;       
      };
      
    • 点类源文件point.cpp(写点类的类定义)

      # include "point.h"
      
      //设置x
      void Point::setX(int x) { 
          m_X = x; 
      } 
      //获取x
      int Point::getX() { 
          return m_X; 
      }    
      //设置y
      void Point::setY(int y) { 
          m_Y = y; 
      } 
      //获取y
      int Point::getY() { 
          return m_Y; 
      }    
      
    • 圆类头文件circle.h(写圆类的类声明)

      # pragma once
      # include 
      using namespace std;
      
      class Circle { //圆类
      public: 
          void setR(int r) { m_R = r; }				        //设置半径    
          int getR(){ return m_R; }						   //获取半径    
          void setCenter(Point center){ m_Center = center; }	 //设置圆心   
          Point getCenter(){ return m_Center; } 				//获取圆心   
      private:
          int m_R;    //半径
          Point m_Center;  //圆心      
      };
      
    • 圆类源文件circle.cpp(写圆类的类定义)

      # include "circle.h"
      
      //设置半径
      void Circle::setR(int r){
          m_R = r;
      }
      //获取半径
      int Circle::getR(){
         return m_R;
      }
      //设置圆心
      void Circle::setCenter(Point center){
          m_Center = center;
      }
      //获取圆心
      Point Circle::getCenter(){
          return m_Center;
      }
      
    • 主函数main.cpp(调用类)

      # include 
      # include "circle.h"
      # include "point.h"
      using namespace std;
      
      //判断点和圆的关系
      void isInCircle(Circle &c, Point &p){
         //计算两点之间距离平方
         int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
                         (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
         //计算半径的平方
         int rDistance = c.getR() * c.getR(); 
         //判断关系
         if(distance == rDistance){
             cout << "点在圆上" << endl; 
         }else if(distance > rDistance){
             cout << "点在圆外" << endl;
         }else{
             cout << "点在圆内" << endl;
         }               
      }
      
      int main(){
          //创建圆
          Circle c;
          c.setR(10);
          Point center;
          center.setX(10);
          center.setY(0);
          c.setCenter(center);
          //创建点
          Point p;
          p.setX(10);
          p.setY(10);
          //判断关系
          isInCircle(c, p);
      }
      

三、结构体

3.1 结构体和类的区别

  • 二者基本没有区别,唯一的区别就是struct的成员的访问控制默认是pubilc,而class默认是private
  • C++中结构体存在的唯一原因是想要维持与C之间的兼容性

3.2 定义和使用

  • 结构体struct是用户自定义的数据类型,允许用户存储不同的数据类型
  • 语法:struct 结构体名 { 结构体成员列表 };
  • 结构体变量创建方式:
    • struct 结构体名 变量名
    • struct 结构体名 变量名 = { 成员1值 , 成员2值…}
    • 定义结构体时顺便创建变量
  • 结构体变量利用操作符 “ . ” 访问成员
//结构体定义
struct student {
	//成员列表
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
} stu3; //结构体变量创建方式3 

int main() {
	//结构体变量创建方式1
	struct student stu1; //struct 关键字可以省略

	stu1.name = "张三";
	stu1.age = 18;
	stu1.score = 100;
	
	cout << "姓名:" << stu1.name << " 年龄:" << stu1.age  << " 分数:" << stu1.score << endl;

	//结构体变量创建方式2
	struct student stu2 = { "李四", 19, 60 };
	cout << "姓名:" << stu2.name << " 年龄:" << stu2.age  << " 分数:" << stu2.score << endl;
	
    //结构体变量创建方式3, 定义结构体时顺便创建变量stu3
	stu3.name = "王五";
	stu3.age = 18;
	stu3.score = 80;
	cout << "姓名:" << stu3.name << " 年龄:" << stu3.age  << " 分数:" << stu3.score << endl;

	return 0;
}

3.3 结构体数组

  • 将自定义的结构体放入到数组中方便维护
  • 语法:struct 结构体名 数组名[元素个数] = { {} , {} , ... {} };
//结构体定义
struct student {
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

int main() {
	//结构体数组
	struct student arr[3] = {
		{"张三", 18, 80 },
		{"李四", 19, 60 },
		{"王五", 20, 70 }
	};

	for (int i = 0; i < 3; i++) {
		cout << "姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 分数:" << arr[i].score << endl;
	}

	return 0;
}

3.4 结构体指针

  • 通过指针访问结构体中的成员
  • 利用操作符 -> 可以通过结构体指针访问结构体属性
struct student {
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

int main() {
	struct student stu = { "张三", 18, 100 };
	struct student * p = &stu;
	p->score = 80; //指针通过 -> 操作符可以访问成员
	cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;

	return 0;
}

3.5 结构体嵌套

//学生结构体定义
struct student {
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

//教师结构体定义
struct teacher {
	int id; 			//职工编号
	string name;  		//教师姓名
	int age;   			//教师年龄
	struct student stu;  //子结构体 学生
};

int main() {
	struct teacher t1;
	t1.id = 10000;
	t1.name = "老王";
	t1.age = 40;
    
	t1.stu.name = "张三";
	t1.stu.age = 18;
	t1.stu.score = 100;
    
	cout << "教师 职工编号: " << t1.id << " 姓名: " << t1.name << " 年龄: " << t1.age << endl;
	cout << "辅导学员 姓名: " << t1.stu.name << " 年龄:" << t1.stu.age << " 考试分数: " << t1.stu.score << endl;
    
	return 0;
}

3.6 结构体做函数参数

  • 将结构体作为参数向函数中传递
  • 值传递和地址传递两种方式
//学生结构体定义
struct student {
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

//值传递
void printStudent(student stu) {
	stu.age = 28;
	cout << "子函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;
}

//地址传递
void printStudent2(student *stu) {
	stu->age = 28;
	cout << "子函数中 姓名:" << stu->name << " 年龄: " << stu->age  << " 分数:" << stu->score << endl;
}

int main() {
	student stu = { "张三",18,100};
	//值传递
	printStudent(stu);
	cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl;

	//地址传递
	printStudent2(&stu);
	cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;

	return 0;
}

3.7 const

  • 用const来防止误操作
struct student {
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};

//const使用场景
//加const防止函数体中的误操作
void printStudent(const student *stu) {
	//stu->age = 100; //操作失败,因为加了const修饰
	cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;
}

int main() {
	student stu = { "张三",18,100 };
	printStudent(&stu);
	return 0;
}

你可能感兴趣的:(C++笔记,c++,开发语言)