本文共 5356 字,大约阅读时间需要 17 分钟。
新的公司,做之前没有做过的工作,全新的开始。由于项目是C++代码写的桌面版设计软件,所以作为测试开发,需要去做C++的白盒和SDK的API自动化测试。虽然,学习过Java这门面向对象编程语言,当前看C++的源码还是很吃力,所以打算,学习一下C++的面向对象部分。写博客,仅仅是督促我自己学习的一个方法,平时不做总结,只好通过写博客来记录学习过程,学习多了,自然就会产生总结和提炼,这需要一个过程。
开发环境+学习视频资料
操作系统:win10 + VS 2017 社区版,需要在VS上登录自己的github账号,否则30天之后,vs2017社区版本不能激活。关于学习资料,这份学习资料是传智播客的老师录制的,可以在B站,搜索 C++匠心之作找到。
面向对象的三大特性:封装,继承,多态
这个和Java是一样,所以面向对象编程语言都有这三大特性,如果是四大特性,就增加一个抽象。在学习封装之前,我们得先学习类。Java和C++一样,认为万物皆对象,对象具有属性和行为。
封装的意义:
1.将属性和行为作为一个整体,表现生活中事物
2.将属性和行为加以权限控制
把行为和属性封装起来成一个整体,在编程语言中,这个叫做类。下面就是封装的定义
封装
封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
定义一个圆类
封装就是从练习设计类开始,这里练习一个圆类,求出圆的周长。
在VS2017里面,新建一个空白的项目,然后在源文件下新建一个cpp文件,一开始我们的代码如下
#includeusing namespace std;int main(){ //这里开始写代码 system("pause"); return 0;}
以后这几行代码,是我们写C++代码开始。加入system("pause")这行代码,使我们在控制台运行代码只会,停留在结果显示,cmd窗口不会自动关闭,pause是暂停的意思。也就是执行以上main函数,只要cmd窗口没有关闭,当前这个main函数就没有走到return 0这行代码,也就是当前main函数运行没有退出,还在内存中跑着程序。
类的定义格式
在C++中,这样去定义一个类
//定义一个类class 类名称{public: //属性 //行为};
注意定义一个类需要英文的分好结尾,这个和Java是不一样的。class是关键字,表示这个是一个类,class后面跟着的是类的名称,里面public: 是权限控制。权限控制有(public, private, protected)3种,如果没有添加任何权限修饰,默认是private。属性就是一些变量的定义,行为一般就是函数或者方法,函数就是解决实际问题。
下面定义一个圆类,我们来简单点,一个圆有一个属性叫做半径R, 有一个行为,也就是方法,叫做计算周长caculateZC()
//设计圆类class Circle{public: //属性 int m_R; //半径 //行为 //设置半径 void setR(int r) { m_R = r; } //计算周长 double caculteZC() { return 2 * 3.14 * m_R; }};
那么如何使用这个类,下面就是介绍在main方法中初始化或者叫实例化一个类对象。
#includeusing namespace std;//设计圆类class Circle{public: //属性 int m_R; //半径 //行为 //设置半径 void setR(int r) { m_R = r; } //计算周长 double caculteZC() { return 2 * 3.14 * m_R; }};int main(){ //实例化一个圆类对象 Circle c; c.setR(10); cout << "圆的周长为:" << c.caculteZC() <
运行结果
总结:
在类中定义的属性,有时候我们叫成员变量 或者类变量
在类中定义的行为,有时候我们叫做成员方法或者成员函数。行为都是一些函数。
关于3种权限总结
公共权限 public 修饰成员 类内可以访问 类外可以访问
保护权限 protected 修饰成员 类内可以访问 类外不可以访问 子类可以访问父类中保护内容 私有权限 private 修饰成员 类内可以访问 类外不可以访问 子类不可以访问父类的私有内容在实际的开发中,我们把成员都写成私有的,提供public的方法,例如set和get方法去设置和获取类的属性。下面来一个例子,关于圆和点的关系。(判断一个点在圆的圆内,圆上,还是圆外)
#includeusing namespace std;//定义一个点类class Point{private: //X坐标 int X; //Y坐标 int Y;public: //设置X void setX(int x) { X = x; } //获取X int getX() { return X; } //设置Y void setY(int y) { Y = y; } //获取Y int getY() { return Y; }};class Circle{private: //半径 int R; //圆心 Point center;public: //设置半径 void setR(int r) { R = r; } //获取半径 int getR() { return R; } //设置圆心 void setCenter(Point p) { center = p; } //获取圆心 Point getCenter() { return center; } //判断点和圆的关系 void getPosition(Point p) { // 两点之间距离(这里不开根号) int distance = (center.getX() - p.getX()) * (center.getX() - p.getX()) + (center.getY() - p.getY()) * (center.getY() - p.getY()); if (distance > R*R) { cout << "在圆外" << endl; } else if (distance < R*R) { cout << "在圆内" << endl; } else { cout << "在圆上" << endl; } }};int main(){ //实例化一个点 Point p; p.setX(10); p.setY(10); //实例化一个圆类对象 Circle c1; c1.setR(10); //圆心 Point cen; cen.setX(10); cen.setY(0); c1.setCenter(cen); c1.getPosition(p); system("pause"); return 0;}
运行上面代码
上面这个点和圆的关系的代码例子,很好体现了封装的特性。我们在点类和圆类中,把属性都用了私有权限,这样只能类内部使用,外部是不可以直接读写类属性。所以,我们需要提供public方法,也就是以上的set和get方法来让外部设置我们属性。这就是封装的作用,只想把能暴露的提供给外界,不想暴露就内部使用私有权限控制。
以上全部代码都混合在一个源码文件中,实际的C++开发中,一个类写一个文件,而且分头文件和源文件,所以,下面我们来修改,拆分这段代码,改成实际开发的编码风格。
1.先分别创建两个类的头文件和源文件(4个空文件)
2.Point.h的内容
#pragma once#includeusing namespace std;//定义一个点类class Point{private: //X坐标 int X; //Y坐标 int Y;public: //设置X void setX(int x); //获取X int getX(); //设置Y void setY(int y); //获取Y int getY();};
在头文件中,只保留类的定义,关于具体方法的实现都删除,具体实现在对应的cpp文件代码中去实现。上面第一行代码#pragma once 是防止头文件重复包含。
3.Point.cpp的内容
#include"Point.h"//设置Xvoid Point::setX(int x){ X = x;}//获取Xint Point::getX(){ return X;}//设置Yvoid Point::setY(int y){ Y = y;}//获取Yint Point::getY(){ return Y;}
上面代码 Point:: 这个语法的是作用范围的限定,告诉当前代码是执行什么类下的行为(方法)。
4.Circle.h内容
#pragma once#include#include "Point.h";using namespace std;class Circle{private: //半径 int R; //圆心 Point center;public: //设置半径 void setR(int r); //获取半径 int getR(); //设置圆心 void setCenter(Point p); //获取圆心 Point getCenter(); //判断点和圆的关系 void getPosition(Point p); };
5.Circle.cpp内容
#include "Circle.h";//设置半径void Circle::setR(int r){ R = r;}//获取半径int Circle::getR(){ return R;}//设置圆心void Circle::setCenter(Point p){ center = p;}//获取圆心Point Circle::getCenter(){ return center;}//判断点和圆的关系void Circle::getPosition(Point p){ // 两点之间距离(这里不开根号) int distance = (center.getX() - p.getX()) * (center.getX() - p.getX()) + (center.getY() - p.getY()) * (center.getY() - p.getY()); if (distance > R*R) { cout << "在圆外" << endl; } else if (distance < R*R) { cout << "在圆内" << endl; } else { cout << "在圆上" << endl; }}
6.main函数
#include "Point.h"#include "Circle.h"int main(){ //实例化一个点 Point p; p.setX(10); p.setY(10); //实例化一个圆类对象 Circle c1; c1.setR(10); //圆心 Point cen; cen.setX(10); cen.setY(0); c1.setCenter(cen); c1.getPosition(p); system("pause"); return 0;}
通过修改p这个点的X轴坐标,X=10在圆上,X=11在圆外,X=9在圆内,可以分别测试三次证明代码的是正确的。
转载地址:http://nqxws.baihongyu.com/