类和对象C++
封装
将属性和行为作为一个整体,表现生活中的事物
封装的意义
#include<iostream>
#include<string.h>
using namespace std;
//设计学生类
class student {
public://公共权限
/*
类中的属性和行为 统一称为成员
属性=成员属性=成员变量
行为=成员函数=成员方法
*/
//属性
string m_Name;//姓名
int m_Id;//学号
//权限/行为
void setName(string name) {
m_Name = name;
}
void setId(int id) {
m_Id = id;
}
void showStudent() {
cout << "name=" << m_Name << " id=" << m_Id << endl;
}
};
int main() {
//创建一个具体的学生——实例化对象
student s1;
//两种赋值方式
//s1.m_Name = "张三";
//s1.m_Id = 11;
s1.setName("张三");
s1.setId(11);
s1.showStudent();
return 0;
}
访问权限
公共权限 public
保护权限 protected
私有权限 private
#include<iostream>
using namespace std;
/*
访问权限
公共权限 public 成员类内可以访问,类外也可以访问
保护权限 protected 类内可以访问,类外不可以访问 儿子可以访问父亲中保护的内容——父亲想让儿子使用的
私有权限 private 类内可以访问,类外不可以访问 儿子不能访问父亲中私有内容——不亲不想让儿子使用的
*/
class Person {
public:
string m_Name;
protected:
string m_Car;
private:
int m_Password;
public:
void func() {
m_Name = "张三";
m_Car = "小米汽车";
m_Password = 123456;
}
};
int main() {
Person p1;
p1.m_Name = "张四";//可以使用
p1.func();//可以使用
//p1.m_Car p1.m_Password 不能访问
return 0;
}
struct和class的区别
#include<iostream>
using namespace std;
//struct默认权限为公共
//class默认权限为私有
class C1 {
int m_A;//默认权限是私有
};
struct C2 {
int m_A;//默认权限是公共
};
int main() {
C1 c1;
C2 c2;
//c1.m_A; 权限是私有,不可以访问
c2.m_A;
return 0;
}
成员属性设置为私有
1.将所有成员属性设置为私有,可以自己控制读写权限
2.对于写权限,可以检测数据的有效性
#include<iostream>
#include<string.h>
using namespace std;
class Person {
//提供公有的方法对私有的属性进行控制
public:
//设置姓名
void setName(string name) {
m_Name = name;
}
//获取姓名
string getName() {
return m_Name;
}
//获取年龄
int getAge() {
return m_Age;
}
//设置年龄0~150
void set_Age(int age) {
if (age < 0 || age > 150) {
cout << "年龄输入有误,赋值失败" << endl;
return;
}
m_Age = age;
}
//设置偶像
void set_Idol(string idol) {
m_Idol = idol;
}
private:
string m_Name;//可读可写
int m_Age = 18;//可读 也可以写(年龄必须在0-150之间)
string m_Idol;//可写
};
int main() {
Person p;
p.setName("张三");
cout << "姓名:" << p.getName() << endl;
p.set_Age(160);
cout << "年龄:" << p.getAge() << endl;
p.set_Idol("卢梭");
return 0;
}
分别用全局函数和成员函数判断两个立方体是否相等
#include<iostream>
using namespace std;
//1.设计立方体类Cube
//2.求出立方体的面积和体积
//3.分别用全局函数和成员函数判断两个立方体是否相等
class Cube {
public:
void setLength(int l) {
m_L = l;
}
int getLength() {
return m_L;
}
void setWeight(int w) {
m_W = w;
}
int getWeight() {
return m_W;
}
void setHeight(int h) {
m_H = h;
}
int getHeight() {
return m_H;
}
//面积
int getArea() {
return 2 * m_H * m_L + 2 * m_H * m_W + 2 * m_L * m_W;
}
//体积
int getVolume() {
return m_H * m_L * m_W;
}
//利用成员函数判断两个立方体是否相等
bool isSameByClass(Cube c1,Cube c2) {
if (c1.m_H == c2.m_H && c1.m_L == c2.m_L && c1.m_W == c2.m_W)
return true;
else return false;
}
private:
int m_W;//宽
int m_L;//长
int m_H;//高
};
//利用全局函数判断
bool isSame(Cube &c1, Cube &c2) {
if (c1.getLength() == c2.getLength() && c1.getHeight() == c2.getHeight() && c1.getWeight() == c2.getWeight())
return true;
else return false;
}
int main() {
Cube c1;
c1.setLength(10);
c1.setWeight(10);
c1.setHeight(10);
cout << c1.getArea() << endl;
cout << c1.getVolume() << endl;
Cube c2;
c2.setLength(10);
c2.setWeight(10);
c2.setHeight(10);
//bool ret = isSame(c1, c2);
bool ret = c1.isSameByClass(c1,c2);
if (ret) cout << "c1=c2" << endl;
else cout << "c1!=c2" << endl;
return 0;
}
判断点和圆的位置关系
//circle.h
#pragma once
#include<iostream>
#include "point.h"
using namespace std;
class Circle {
private:
int c_R;//半径
Point c_Center;//圆心
public:
void setCenter(Point center);
//获取圆心
Point getCenter();
void setR(int r);
int getR();
};
//point.h
#pragma once
#include<iostream>
using namespace std;
class Point {
private:
int p_X;
int p_Y;
public:
void setX(int x);
int getX();
void setY(int y);
int getY();
};
circle.cpp
#include "circle.h"
void Circle::setCenter(Point center) {
c_Center = center;
}
//获取圆心
Point Circle::getCenter() {
return c_Center;
}
void Circle::setR(int r) {
c_R = r;
}
int Circle::getR() {
return c_R;
}
//Circle:: 是加上作用域
//point.cpp
#include "point.h"
void Point::setX(int x) {
p_X = x;
}
int Point::getX() {
return p_X;
}
void Point::setY(int y) {
p_Y = y;
}
int Point::getY() {
return p_Y;
}
//main
#include<math.h>
#include<iostream>
using namespace std;
#include "point.h"
#include "circle.h"
//判断点和圆的关系
void isInCircle(Circle &c,Point &p) {
int t;
t=pow(c.getCenter().getX() - p.getX(), 2) + pow(c.getCenter().getY() - p.getY(), 2);
int r = c.getR();
if(t < r*r)
cout << "点在圆内" << endl;
else if (t == r*r)
cout << "点在圆上" << endl;
else
cout << "点在圆外" << endl;
}
int main() {
//创建圆
Circle c1;
Point center;
c1.setR(5);
center.setX(0);
center.setY(0);
c1.setCenter(center);
//创建点
Point p;
p.setX(3);
p.setY(4);
//判断关系
isInCircle(c1, p);
return 0;
}
.h 文件中只写声明
.cpp 文件中只写实现
把类的声明和实现分开写
对象特征
构造函数/析构函数
#include<iostream>
using namespace std;
//对象的初始化和清理
class Person {
public:
//1.构造函数 进行初始化
//编译器自动调用一次
Person() {
cout << "Person 构造函数调用" << endl;
}
//2.析构函数 进行清理的操作
//程序结束前调用
~Person() {
cout << "Person 析构函数调用" << endl;
}
};
void test() {
Person p;
}
int main() {
test();
//Person p;
system("pause");
return 0;
}
构造函数的分类及其调用
#include<iostream>
using namespace std;
//1.构造函数的分类和调用
//分类
//按照参数分类 无参构造(默认构造函数) 和 有参构造
//按照类型分类
class Person {
public:
int age;
Person() {
cout << "Person无参构造函数" << endl;
}
Person(int a) {
age = a;
cout << "Person有参构造函数" << endl;
}
//拷贝构造函数
Person(const Person &p) {
//将传入的人身上的所有属性,拷贝到我身上
age = p.age;
cout << "Person 拷贝构造函数" << endl;
}
};
//调用
void test() {
//1.括号法
Person p1;//默认构造函数调用,不要加(),因为会认为是函数声明
Person p2(10);
Person p3(p2);
//2.显示法
Person p1;
Person p2 = Person(10);//有参构造
Person p3 = Person(p2);//拷贝构造
//Person(10); //匿名对象 特点:当前行执行结束后,系统会立即回收掉匿名对象
//cout << "aaa" << endl;
//不要利用拷贝构造函数 初始化匿名对象。编译器会认为是声明
//3.隐式转换法
Person p4 = 10; //相当于 Person p4 = Person(10);
Person p5 = p4; //拷贝构造
}
int main() {
test();
system("pause");
return 0;
}
构造函数调用规则
深拷贝/浅拷贝
初始化列表
#include<iostream>
using namespace std;
//初始化列表
class Person {
public:
//传统初始化操作
/*Person(int a,int b,int c) {
m_A = a;
m_B = b;
m_C = c;
}*/
//初始化列表
/*Person() :m_A(10), m_B(20), m_C(30) {
}*/
Person(int a,int b,int c) :m_A(a), m_B(b), m_C(c) {
}
int m_A;
int m_B;
int m_C;
};
void test01() {
//Person p(10, 20, 30);//创建对象
//Person p;
Person p(30, 20, 10);
cout << "m_A=" << p.m_A << endl;
cout << "m_B=" << p.m_B << endl;
cout << "m_c=" << p.m_C << endl;
}
int main() {
test01();
system("pause");
return 0;
}
类对象作为类成员
#include<iostream>
#include<string.h>
using namespace std;
//类对象作为类成员
//B类中有对象A作为成员,A为对象成员
//手机类
class Phone {
public:
//手机品牌名称
string m_PName;
Phone(string pName) {
m_PName = pName;
cout << "Phone的构造函数调用" << endl;
}
};
//人类
class Person {
public:
//姓名
string m_Name;
//手机
Phone m_Phone;
//隐式转换
Person(string name, string pName):m_Name(name),m_Phone(pName)
{
cout << "Person的构造函数调用" << endl;
}
};
//测试案例
void test01() {
Person p("张三", "华为");
cout << p.m_Name << "拿着" << p.m_Phone.m_PName << "手机" << endl;
}
int main() {
test01();
//system("pause");
return 0;
}
静态成员 static
静态成员变量/静态成员函数
#include<iostream>
using namespace std;
class Person {
public:
//1.所有对象都共享同一份数据
//2.编译阶段就分配内存
//3.类内声明,类外初始化操作
static int m_A;
//静态成员变量访问权限
private:
static int m_B;
};
int Person::m_A = 100;//Person作用域下
int Person::m_B = 4;
void test01() {
Person p;
cout << p.m_A << endl;//100
Person p2;
p2.m_A = 200;
cout << p.m_A << endl;//200 m_A是共享的
}
void test02() {
//静态成员变量 不属于某个对象上,所有对象都共享同一份数据
//因此静态成员变量有两种访问方式
//1.通过对象进行访问
Person p;
cout << p.m_A << endl;
//2.通过类名进行访问
cout << Person::m_A << endl;
//cout << Person::m_B << endl; //报错,私有权限类外不能访问
}
int main() {
//test01();
test02();
system("pause");
return 0;
}
C++对象模型和this指针
成员变量和成员函数分开存储
#include<iostream>
using namespace std;
//成员变量和成员函数分开存储
//*只有非静态成员变量才属于类的属性上
class Person {
};
void test01() {
Person p;
//空对象占用内存空间为:1
//为了区分空对象占内存的位置
//每个空对象也应该有一个独一无二的内存地址
cout << "size of p= " << sizeof(p) << endl;
}
void test02() {
int m_A;//非静态成员变量 属于类的对象 大小为4
static int m_B;//静态成员变量 不属于类的对象上 加上它还是4
//void func() {} //非静态成员函数 不属于类的对象 还是4
//静态成员函数 不属于类的对象
}
int main() {
test01();
system("pause");
return 0;
}
this指针
谁调用它,就指向谁
#include<iostream>
using namespace std;
class Person {
public:
Person(int age) {
//this指针指向的是 被调用的成员函数所属的对象
this->age = age;
}
int age;
Person& PersonAddAge(Person &p) {
this->age += p.age;
//返回对象指针
return *this;
}
};
//1.解决名称冲突
void test01() {
Person p1(18);
cout <<"p1的年龄为:" << p1.age << endl;
}
//2.返回对象本身用 *this
void test02() {
Person p1(10);
Person p2(10);
//链式编程思想 p2 = p2+p1+p1+p1
p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
cout << "p2的年龄为:" << p2.age << endl;
}
int main() {
test01();
test02();
system("pause");
return 0;
}
空指针访问成员函数
#include<iostream>
using namespace std;
//空指针调用成员函数
class Person {
public:
void showClassName() {
cout << "this is Person class" << endl;
}
void showPersonAge() {
//报错原因是因为传入的指针是NULL
if (this == NULL)
return;
cout << "age=" << m_Age << endl;
}
int m_Age;
};
void test01() {
Person* p = NULL;
p->showClassName();
p->showPersonAge();
}
int main() {
test01();
system("pause");
return 0;
}
const修饰成员函数
const 加的位置
加mutable 使之可以修改
友元
#include<iostream>
#include<string.h>
using namespace std;
//友元的目的就是让一个函数或者类 访问另一个类中私有成员
//友元的关键字为 friend
//友元的三种实现
//1.全局函数做友元
//2.类做友元
//3.成员函数做友元
class Building
{
friend void goodGay(Building* building);//声明放类里,前面加上friend
public:
Building()//类内写成员函数
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
public:
string m_SittingRoom;//客厅
private:
string m_BedRoom;//卧室
};
//1.全局函数做友元
void goodGay(Building* building)//指针
{
cout << "好朋友全局函数 正在访问:" << building->m_SittingRoom << endl;
cout << "好朋友全局函数 正在访问:" << building->m_BedRoom << endl;
}
int main() {
Building building;
goodGay(&building);
system("pause");
return 0;
}
运算符重载
对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
加法运算符重载
#include<iostream>
using namespace std;
//对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
//加号运算符重载
//实现任意类型的数相加
//1.通过成员函数重载+号
//2.通过全局函数重载+号
class Person
{
public:
//1.通过成员函数重载+号
/*Person operator+(Person& p)
{
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}*/
int m_A;
int m_B;
};
//2.通过全局函数重载+号
Person operator+(Person& p1, Person& p2)
{
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_B + p2.m_B;
return temp;
}
void test01()
{
Person p1;
p1.m_A = 1;
p1.m_B = 2;
Person p2;
p2.m_A = 3;
p2.m_B = 4;
Person p3 = p1 + p2;
cout << "p3.m_A=" << p3.m_A << endl;
cout << "p3.m_B=" << p3.m_B << endl;
}
int main() {
test01();
return 0;
}
左移运算符重载
#include<iostream>
using namespace std;
//左移运算符重载
class Person
{
friend ostream& operator<<(ostream& cout, Person& p);
public:
Person(int a, int b)
{
m_A = a;
m_B = b;
}
private:
//利用成员函数重载 左移运算符
int m_A;
int m_B;
};
//只能利用全局函数重载左移运算符
ostream & operator<<(ostream &cout,Person &p)//本质 operator<<(cout,p) 简化 cout<<p
{
cout << "m_A=" << p.m_A << " m_B=" << p.m_B;
return cout;
}
void test01()
{
Person p(2, 3);
cout << p << endl;;
}
int main() {
test01();
system("pause");
return 0;
}
递增/赋值/关系/函数调用运算符重载
继承
语法 class 子类 :继承方式 父类
继承方式:public、protected、private
子类=派生类
父类=基类
#include<iostream>
using namespace std;
class base1 {
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class son1 : public base1 {
public:
void fun() {
m_A = 10;
m_B = 10;
//m_C = 10; 私有儿子不能访问
}
};
class son2 :protected base1 {
public:
void fun() {
m_A = 10;//父类中 public成员,到子类中变为保护权限
m_B = 10;
//m_C = 10; 私有儿子不能访问
}
};
class son3 :private base1 {
public:
void fun() {
m_A = 10;//父类中 public成员,到子类中变为 private成员
m_B = 10;
//m_C = 10; 私有儿子不能访问
}
};
class GrandSon3 :public son3 {
public:
void fun() {
//m_A = 10; m_B = 10; 私有,son3的儿子GrandSon3不能访问
}
};
void text01() {
son1 s1;
s1.m_A = 100;
//s1.m_B 到 son1中 m_B是保护权限 类外访问不到
son2 s2;
//s2.m_A s2.m_B 到 son1中m_A、m_B是保护权限 类外访问不到
son3 s3;
//s3.m_A s3.m_B 到 son3中m_A、m_B是私有成员
}
int main() {
text01();
system("pause");
return 0;
}
//父类中所有非静态成员属性都会被子类继承下去
//父类中private成员属性 是被编译器隐藏了 但继承下去了
多继承
#include<iostream>
using namespace std;
class Base1 {
public:
Base1(){
m_A = 100;
}
int m_A;
};
class Base2 {
public:
Base2() {
m_A = 200;
}
int m_A;
};
//多继承--继承多个父类
class Son : public Base1 , public Base2{
public:
Son() {
m_C = 300;
m_D = 400;
}
int m_C;
int m_D;
};
void text01() {
Son s;
cout << sizeof(s) << endl;//16
//父类中出现同名成员,需要加作用域区分
cout << s.Base1::m_A << endl;
}
int main() {
text01();
//system("pause");
return 0;
}
菱形继承
继承之前 加上关键字 virtual变为虚继承
#include<iostream>
using namespace std;
//菱形继承
//动物类
class Animal {
public:
int m_Age;
};
//利用虚继承可以解决菱形继承的问题
// 继承之前 加上关键字 virtual变为虚继承
// Animal类称为 虚基类
//羊类
class Sheep : virtual public Animal {};
//驼类
class Tuo :virtual public Animal {};
//羊驼类
class SheepTuo :public Sheep, public Tuo {};
void text01() {
SheepTuo st;
st.Sheep::m_Age = 18;
st.Tuo::m_Age = 28;
cout << st.Sheep::m_Age << endl;
cout << st.Tuo::m_Age << endl;
cout << st.m_Age << endl;
//这个数据只需要一份
}
int main() {
text01();
//system("pause");
return 0;
}
多态
一个接口有多种形态
#include<iostream>
using namespace std;
//动态多态:派生类和虚函数实现运行时多态
//晚绑定--运行阶段确定函数地址
//动态多态满足条件
//1.有继承关系
//2.子类重写父类的虚函数
//动态多态使用
//父类的指针或者引用 执行子类对象
class Animal {
public:
//虚函数
virtual void speak() {
cout << "动物说话" << endl;
}
};
class Cat : public Animal{
public:
//重写 函数返回值类型 函数名 参数列表 完全相同
void speak() {
cout << "小猫说话" << endl;
}
};
class Dog : public Animal {
public:
void speak() {
cout << "小狗说话" << endl;
}
};
//说话函数
void doSpeak(Animal &animal) {
animal.speak();
}
void test() {
Cat cat;
doSpeak(cat);
Dog dog;
doSpeak(dog);
}
int main() {
test();
return 0;
}
#include<iostream>
#include<string.h>
using namespace std;
//多态的优点
//1.代码组织结构清晰
//2.可读性强
//3.利于前期和后期的扩展以及维护
//分别利用普通写法和多态技术实现计算器
//普通写法
class Calculator {
public:
int GetResult(string oper) {
if (oper == "+")
return m_Num1 + m_Num2;
else if (oper == "-")
return m_Num1 - m_Num2;
else if (oper == "*")
return m_Num1 * m_Num2;
else if (oper == "/")
return m_Num1 / m_Num2;
}
int m_Num1;
int m_Num2;
};
void test01() {
Calculator c;
c.m_Num1 = 10;
c.m_Num2 = 2;
cout << c.m_Num1 << "+" << c.m_Num2 << "=" << c.GetResult("+") << endl;
cout << c.m_Num1 << "-" << c.m_Num2 << "=" << c.GetResult("-") << endl;
cout << c.m_Num1 << "*" << c.m_Num2 << "=" << c.GetResult("*") << endl;
cout << c.m_Num1 << "/" << c.m_Num2 << "=" << c.GetResult("/") << endl;
}
//多态写法
//实现计算器抽象类
class AbstractCalculator {
public:
virtual int getResult() {//父类有抽象方法
return 0;
}
int m_Num1;
int m_Num2;
};
//加法计算器类
class AddCalculator : public AbstractCalculator {//子类有继承
public:
int getResult() {//重写父类抽象方法
return m_Num1 + m_Num2;
}
};
//减法计算器类
class SubCalculator : public AbstractCalculator {
public:
int getResult() {
return m_Num1 - m_Num2;
}
};
void test02() {
//多态使用条件
//父类指针或者引用指向子类对象
//加法
AbstractCalculator* abc = new AddCalculator;//父类指针
abc->m_Num1 = 3;
abc->m_Num2 = 5;
cout << abc->m_Num1 << "+" << abc->m_Num2 << "=" << abc->getResult() << endl;
//用完要销毁
delete(abc);
//减法
abc = new SubCalculator;
abc->m_Num1 = 4;
abc->m_Num2 = 3;
cout << abc->m_Num1 << "-" << abc->m_Num2 << "=" << abc->getResult() << endl;
delete(abc);
}
int main() {
//test01();
test02();
return 0;
}
纯虚函数和抽象类
#include<iostream>
using namespace std;
//纯虚函数和抽象类
class Base {
//抽象类
//1.无法实例化对象
//2.抽象类的子类 必须要重写父类中的纯虚函数
public:
virtual void func() = 0;//纯虚函数语法
};
class Son : public Base {
public:
virtual void func() {
cout << "func" << endl;
}
};
void test01() {
//Base b; 抽象类无法实例化对象
Son s;
Base* base = new Son;//创建子类对象
base->func();//调用子类的函数
}
int main() {
test01();
return 0;
}
#include<iostream>
using namespace std;
//制作饮品
class AbstractDrinking {
public:
//煮水
virtual void Boil() = 0;
//冲泡
virtual void Brew() = 0;
//倒入杯中
virtual void PourInCup() = 0;
//加入辅料
virtual void PutSomething() = 0;
//制作饮品
void makeDrink() {//函数调用具体的实现
Boil();
Brew();
PourInCup();
PutSomething();
}
};
class Coffee :public AbstractDrinking {
public:
//煮水
virtual void Boil() {
cout << "煮矿泉水" << endl;
};
//冲泡
virtual void Brew() {
cout << "冲泡咖啡" << endl;
};
//倒入杯中
virtual void PourInCup() {
cout << "倒入杯中" << endl;
};
//加入辅料
virtual void PutSomething() {
cout << "加入糖" << endl;
};
};
class Tea : public AbstractDrinking {
public:
//煮水
virtual void Boil() {
cout << "煮山泉水" << endl;
};
//冲泡
virtual void Brew() {
cout << "冲泡茶叶" << endl;
};
//倒入杯中
virtual void PourInCup() {
cout << "倒入杯中" << endl;
};
//加入辅料
virtual void PutSomething() {
cout << "加入柠檬" << endl;
};
};
void doWork(AbstractDrinking* abs) {
abs->makeDrink();//调用父类中的函数
delete abs;//释放
}
void test01() {
doWork(new Coffee);
cout << "-------------" << endl;
doWork(new Tea);
}
int main() {
test01();
return 0;
}
#include<iostream>
#include<string.h>
using namespace std;
//虚析构和纯虚析构
class Animal {
public:
Animal() {
cout << "Animal构造函数调用" << endl;
}
//虚析构 可以解决父类指针释放子类对象不干净的问题
/*virtual ~Animal() {
cout << "Animal析构函数调用" << endl;
}*/
//纯虚析构
virtual ~Animal() = 0;//声明
//纯析函数
virtual void speak() = 0;
};
//具体实现
Animal::~Animal() {
cout << "Animal纯虚析构函数调用" << endl;
}
class Cat :public Animal {
public:
Cat(string name) {
m_Name = new string(name);//堆区创建属性
cout << "Cat构造函数调用" << endl;
}
virtual void speak() {
cout <<*m_Name<< "猫说话" << endl;
}
~Cat() {//析构函数释放堆区数据
if (m_Name != NULL) {
cout << "Cat析构函数调用" << endl;
delete m_Name;
m_Name = NULL;
}
}
string *m_Name;//猫名字,指针
};
void test01() {
Animal* animal = new Cat("咪咪");//创建一个具体的猫对象
animal->speak();//调用说话函数
delete animal;
}
int main() {
test01();
return 0;
}