前言
面向对象编程(OOP)是一种特殊的、设计程序的概念性方法,c++通过一些特性改进了C语言,使得应用这种方法更容易。一、OOP特性
- 抽象的;
- 封装和数据隐藏;
- 多态;
- 继承;
- 代码的可重用性。
C++为了实现这些特性并将它们组合在一起,C++所做的最重要的改进是提供了类。
二、抽象和类
简单的理解抽象和类,就是将具有相同特性的一类东西抽象为一个类。
例如:人分为男人、女人、人妖…可能还有其它类,无论有多少种,它们都具有相同的特性,如,人都有五官、四肢…人都会走路、睡觉、吃饭…因此可以将人抽象为一个类。
C++中的类
首先,类是将抽象转换为用户定义类型的C++工具,也就是说类表达了我们生活中抽象出来的东西或事物,它将数据表示和操纵数据的方法组合成一个整洁的包。
例如:现在把人这一类抽象出来,首先,人都有名字,年龄,性别…代表数据;人需要吃喝拉撒…代表函数方法;在这里将人用一个类来表示,将来我们形容一个具体的人“阿狗”、“阿猫”…的时候,直接对人这个类进行实例化即可。
接下来定义类。一般来说,类的规范有两个部分组成:
-
类声明:以数据成员的方式描述数据部分,以成员函数(被称为方法)的方法描述接口。
-
类方法定义:描述如何实现成员函数。
通常,类声明放在头文件中,类的定义也就是类成员的实现放在源文件中。
示例:
第一步:声明类
创建Person.h头文件,并编写代码如下,用来限制该头文件只包含一次。#ifndef PERSON_H_ #define PERSON_H_ ... #endif
声明类
#ifndef PERSON_H_
#define PERSON_H_
#include <string>
class Person{
//声明成员方法
public:
void setAge(int age);
void setName(const std::string& name);
void setSex(const std::string& sex);
void showPersonInfo();
//声明成员函数或成员变量
private:
int m_nAge;
std::string m_strName;
std::string m_strSex;
std::string m_strPersonInfo;
void getPersonInfo();
};
#endif
首先使用class关键字定义一个Person类,代表人类,其次就是“{};”,代表的是这个类的作用域。然后是public和private两个关键字,代表着访问权限,其权限示意如下:
public:“public:”后面的内容知道遇到下一个访问控制符,所包含的成员函数或成员变量都是公有 的、公开的;实例化这个类的对象可以直接使用这些方法或成员变量;
private:“private:”后面的内容直到遇到下一个访问控制符,多包涵的成员函数或成员变量都是私有的,只能是类成员函数可以访问,或者是“友元类友元函数”可以访问。是类成员而不是对象或者对象成员(对象就没有成员,它是被实例化出来以后使用的是类成员);
protected:待补充。
一般规则:一般将公有接口与实现分开。数据一般设置为私有的,这也是符合了OOP理念,数据隐藏,也是一种封装。
实现类成员函数
定义成员函数时,使用作用域解析运算符(::)来标识函数所属的类;类方法可以访问私有的类方法。实现如下:
#include "Person.h"
#include <iostream>
void Person::setAge(int age)
{
m_nAge = age;
}
void Person::setName(const std::string& name)
{
m_strName = name;
}
void Person::setSex(const std::string& sex)
{
m_strSex = sex;
}
void Person::showPersonInfo()
{
getPersonInfo();
std::cout << m_strPersonInfo;
}
void Person::getPersonInfo()
{
m_strPersonInfo = "姓名:"+ m_strName + "年龄:" + std::to_string(m_nAge) + "性别:" << m_strSex;
}
创建对象
像标准数据类型一样,类是我们自定义类型,因此创建一个对象的形式自然和创建其他变量无两样,如下:
Person zhangsan,lisi,wangwu;
所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享同一组类的方法,即每种方法只有一个副本。如上面zhangsan 、lisi、wangwu都是Person的对象,它们使用的是同一块代码,只是将这些代码用于不同的数据,也就是数据最终存储的位置还是不一样的。就像生活中的建筑工人,所有房子的建筑用的都是这些人,但是盖的位置不一样。
使用类
完成创建对象,就可以对创建出来的对象进行操作了,如下:
Person zhangsan,lisi,wangwu;
zhangsan.setName("张三");
zhangsan.setSex("男");
zhangsan.setAge(18);
zhangsan.showPersonInfo();
lisi.setName("李四");
lisi.setSex("女");
lisi.setAge(18);
lisi.showPersonInfo();
zhangsan.setName("王五");
zhangsan.setSex("人妖");
zhangsan.setAge(18);
zhangsan.showPersonInfo();
类和结构的区别
类和结构唯一区别就是默认的访问权限,类的默认访问权限是私有的,而结构的默认访问权限是共有的。
类的构造函数和析构函数
通常,定义类时需要为类提供构造函数和析构函数的标准函数;
构造函数
一般情况下,在创建类对象的时候,都要对成员变量进行一个初始化,防止出现未知错误。而初始化的事一般都交给构造函数来做。
当实例化Person类对象时,直接Person objectName;即可完成了创建对象的过程,但并没有对成员变量进行初始化操作。
声明和定义类的构造函数,并对成员变量进行初始化操作。格式为:className(dataType param1,dataType param2…);
在Person类中添加构造函数:
Person(int age = 0,const std::string& name = "", const std::string& sex = "");
Person::Person(int age /*= 0*/,const std::string& name /*= ""*/, const std::string& sex /*= ""*/)
{
m_strName = name;
m_nAge = age;
m_strSex = sex;
}
**构造函数的参数表示的不是类成员变量,不能与类成员变量重名,避免混乱。**
使用构造函数:
Person maLiu(118,"马六","太监");
maLiu.showPersonInfo();
默认构造函数
默认构造函数是在为声明和定义显示的提供初始值时,用来创建对象的构造函数,像**Person zhangsan,lisi,wangwu;**就是使用的默认构造,如果没有提供任何构造函数的情况下,C++会提供一个默认构造函数。它是默认构造函数的隐式版本,不做任何工作。对于Person类来说,默认构造函数可能如下:
Person::Person(){}
因此,类本身尽可能提供一个默认构造,默认构造如上,并对数据成员进行初始化操作,代码如下:
Person();
Person::Person()
{
m_strName = "";
m_nAge = 0;
m_strSex = "";
}
析构函数
用构造函数创建对象后,程序负责跟踪该对象,直到其过期位置。对象过期时,程序将自动调用一个特殊的成员函数,析构函数;析构函数完成清理工作,因此实际上很有用,例如在构造函数中使用new 类分配了内存,则在析构函数中将使用delete类释放这些内存。
析构函数的一般形式为:ClassName::~ClassName(){};
调用析构函数的时机:这个由编译器决定,通常不应该在代码中显式的调用这个函数(当然也有例外情形)。
在对象过期时,析构函数将会被自动调用,因此必须有一个析构函数。如果程序员没有提供析构函数,编译器将隐式声明一个默认的析构函数,并在发现导致对象被删除后的代码后,提供默认析构函数的定义。
Person类的析构函数如下:
~Person();
Person::~Person()
{
}