面向对象编程自学笔记整理
十一_一、类与对象
1、类和对象
类和对象.cpp
/************************1.封装—属性和行为作为整体******************************/
//C++面向对象的三大特性:封装,继承,多态
//C++中万物皆为对象,对象上有属性和行为
//类:具有相同性质的对象抽象为一类
//封装意义
/*
1.将属性和行为作为一个整体,表现生活中的事物
2.将属性和行为加以权限控制
*/
//#include<iostream>
//using namespace std;
//
圆周率
//const double PI = 3.14;
设计一个圆类,求圆的周长
周长公式:2*PI*R
//
class代表一个类,后面紧跟为类名称
//class Circle
//{
// //访问权限
// //公共权限
//public:
属性
// double C_R;//半径
行为
// //获取圆周长
// double calculate()
// {
// return 2 * PI * C_R;
// }
//};
//
//int main()
//{
通过圆类,创建具体的圆(对象)
// Circle c1;//实例化一个对象c1
// c1.C_R = 10;
// //2*PI*C_R=62.8
// cout << "圆的周长=" << c1.calculate() << endl;
// system("pause");
// return 0;
//}
/****************************封装的练习-定义学生的类******************************/
//#include<iostream>
//using namespace std;
//
//class Student
//{
//public://公共权限
//
// //类中的属性和行为,统一称为成员
// //属性 成员属性 成员变量
// //行为 成员函数 成员方法
// //属性
// char name[20];//姓名
// char NUM[20];//学号
// //行为
// void showfunc()
// {
// cout << "姓名:" << name << endl
// << "学号:" << NUM << endl;
// }
//};
//int main()
//{
// Student S1;
// cout << "输入姓名:";
// cin >> S1.name;
// cout << "输入学号:";
// cin >> S1.NUM;
// system("cls");
// S1.showfunc();
// system("pause");
// return 0;
//}
/****************************封装-访问权限******************************/
//#include<iostream>
//#include<string.h>
//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 = 12345;
// }
//
//};
//int main()
//{
// //实例化具体对象
// person p1;
//
// p1.m_name = "李四";
// p1.m_car = "奔驰";//保护权限内容,在类外访问不到
// p1.m_password = "147258";//私有权限内容,类外访问不到
// p1.func();
//
// system("pause");
// return 0;
//}
/****************************struct和class的区别******************************/
//#include<iostream>
//using namespace std;
//
//class C1
//{
// int m_a;//默认为私有
//};
//
//struct C2
//{
// int m_a;//默认为公共
//};
//
//int main()
//{
// //区别:默认的访问权限不同
// //struct:默认权限为公共
// //class:默认权限为私有
// C1 c1;
// c1.m_a=100;
// C2 c2;
// c2.m_a=10;
// system("pause");
// return 0;
//}
/****************************成员属性设为私有******************************/
//#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()
// {
// //m_age = 0;//初始化为0
// return m_age;
// }
// //设置年龄接口,可读可写,想要修改(年龄范围1—150)
// void setage(int age)
// {
// if(age < 0 || age>150)//或操作
// {
// m_age = 0;
// cout << "你这个老妖精!" << endl;
// return;
// }
// m_age = age;
// }
//
// //写情人接口 只写
// void setlover(string lover)
// {
// m_lover = lover;
// }
//
//private:
// string m_name;//姓名 可读可写
// int m_age;//年龄 只读
// string m_lover;//情人 只写
//};
//int main()
//{
// //优点1:设为私有可以自己控制读写权限
// //优点2:对于写权限,可以检测数据的有效性
// person p;
// p.setname("张三");
// cout << "姓名为:" << p.getname() << endl;
// //p.m_age = 18;只读操作
// p.setage(180);
// cout << "年龄为:" << p.getage() << endl;
// p.setlover("苍井");
// //cout << "情人为:" << p.getlover() << endl;//只写操作
// system("pause");
// return 0;
//}
/****************************封装案例1-设置立方体类******************************/
//设置类,求出立方体的面积和体积
//分别用全局函数和成员函数判断两个立方体是否相等
//#include<iostream>
//using namespace std;
//
//class cube
//{
//public:
// //行为
// //1.设置立方体的长宽高
// void set(int L, int W, int H)
// {
// m_L = L;
// m_W = W;
// m_H = H;
// }
// //2.获取立方体的长宽高
// int get()
// {
// /*cout << "该立方体长L=" << m_L
// << " 该立方体宽W = " << m_W
// << " 该立方体高H = " << m_H;
// cout << endl;*/
// return m_L;
// return m_W;
// return m_H;
// }
//
// //3.获取立方体面积
// void cubeS()
// {
// double S;
// S = (2 * m_L * m_W) +(2*m_L* m_H)+(2*m_W*m_H);
// cout << "该立方体的表面积S=" << S << endl;
// }
// //4.获取立方体体积
// void cubeV()
// {
// double V;
// V = m_L * m_W * m_H;
// cout << "该立方体体积V=" << V << endl;
// }
//
// //5.分别用全局函数和成员函数判断两个立方体是否相等
// bool issameByclass(cube &C)
// {
// if (C.m_L ==m_L&& C.m_W == m_W&& C.m_H ==m_H)
// {
// return true;
// }
// else
// return false;
// }
//
//
//private:
// //属性
// int m_L;//长
// int m_W;//宽
// int m_H;//高
//};
//
利用全局函数判断两个立方体是否相等
//bool issame(cube& C1, cube& C2)
//{
// if (C1.get() == C2.get())
// {
// return true;
// }
// else
// return false;
//}
//
//
//int main()
//{
// //创建立方体对象1
// cube C1;
// C1.set(1, 5, 6);
// C1.get();
// C1.cubeS();
// C1.cubeV();
// //创建立方体对象2
// cube C2;
// C2.set(4, 5, 6);
// C2.get();
// //利用全局函数判断两个立方体是否相等
// bool ret1 = issame(C1, C2);
// if (ret1)
// {
// cout << "全局函数判断C1和C2是相等的" << endl;
// }
// else
// {
// cout << "全局函数判断C1与C2不相等" << endl;
// }
// //利用类内函数判断两个立方体是否相等
// bool ret2 = C1.issameByclass(C2);
// if (ret2)
// {
// cout << "成员函数判断C1和C2是相等的" << endl;
// }
// else
// {
// cout << "成员函数判断C1与C2不相等" << endl;
// }
// system("pause");
// return 0;
//}
/****************************封装案例2-点和圆的关系判断******************************/
#include<iostream>
#include"point.h"
#include"circle.h"
using namespace std;
//点和圆的关系判断
点类
//class point
//{
//public:
// //设置圆心坐标的接口
// void set(int X, int Y)
// {
// m_x = X;
// m_y = Y;
// }
// //获取圆心坐标的接口
// int getX()
// {
// return m_x;
// }
// int getY()
// {
// return m_y;
// }
//private:
// double m_x;
// double 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:
// double m_R;//半径
// //在一个类中,可以让另一个类作为本类中的成员
// point m_center;//圆心坐标
//};
//判断点和圆的位置关系的函数
void isincircle(circle& c, point& p)
{
//计算两点之间的距离的平方
double distance;
distance = (c.getcenter().getX() - p.getX()) * (c.getcenter().getX() - p.getX()) +
(c.getcenter().getY() - p.getY()) * (c.getcenter().getY() - p.getY());
//计算半径的平方
double R distance = c.getR() * c.getR();
//判断二者关系
if (distance == Rdistance)
{
cout << "点在圆上!"<<endl;
}
else if (distance > Rdistance)
{
cout << "点在圆外!" << endl;
}
else if (distance < Rdistance)
{
cout << "点在圆内!" << endl;
}
}
int main()
{
//创建圆
circle c;
c.setR(10);
point center;
center.set(10,0);
c.setcenter(center);
//创建点
point p;
p.set(10, 12);
//判断关系
isincircle(c,p);
system("pause");
return 0;
}
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;
}
circle.h
#pragma once
#include<iostream>
#include"point.h"
using namespace std;
//圆类
class circle
{
public:
//设置半径
void setR(int R);
//获取半径
int getR();
//设置圆心
void setcenter(point center);
//获取圆心
point getcenter();
private:
double m_R;//半径
//在一个类中,可以让另一个类作为本类中的成员
point m_center;//圆心坐标
};
point.cpp
#include"point.h"
//点类
//设置圆心坐标的接口
void point::set(int X, int Y)
{
m_x = X;
m_y = Y;
}
//获取圆心坐标的接口
int point::getX()
{
return m_x;
}
int point::getY()
{
return m_y;
}
point.h
#pragma once
#include<iostream>
using namespace std;
//点类
class point
{
public:
//设置圆心坐标的接口
void set(int X, int Y);
//获取圆心坐标的接口
int getX();
int getY();
private:
double m_x;
double m_y;
};
2、对象特征_构造函数和析构函数
/**********************1.对象特征*****************************************/
构造函数:创建对象时为对象成员属性赋值,构造函数由编译器自动调用
析构函数:对象销毁前系统自动调用,执行一些清理工作
//#include<iostream>
//using namespace std;
//
对象的初始化和清理
//class person
//{
//public:
// //1.构造函数 进行初始化操作
// //构造函数语法 类名(){}
// //构造函数没有返回值也不写void
// //函数名称与类名相同
// //构造函数可以有参数,因此可以发生重载
// //程序在调用对象时会自动调用构造,无需手动调用,且只会调用一次
// person()
// {
// cout << "person构造函数的调用" << endl;
// }
// //2.析构函数 进行清理操作
// //析构函数语法 ~类名(){}
// //析构函数没有返回值也不写void
// //函数名称与类名相同,前面加上~
// //析构函数不可以有参数,不发生重载
// //程序在对象销毁前自动调用析构,无需手动调用,且只会调用一次
// ~person()
// {
// cout << "person析构函数的调用" << endl;
// }
//};
构造和析构都是必须要有的实现,若我们自己不提供,编译器会提供一个空实现的构造和析构
//void test01()
//{
// person p;//在栈上的数据,test01执行完毕后,释放这个对象
//}
//
//int main()
//{
// //person p;
// test01();
// system("pause");//代码暂停,不会执行接下来的析构函数
// return 0;
//}
/**********************2.构造函数的分类与调用*****************************************/
//#include<iostream>
//using namespace std;
//
//
//class person
//{
//public:
// //按参数分为:有参构造和无参构造(默认构造函数)
// //按类型分为:普通构造和拷贝构造
// //构造函数
// person()//无参
// {
// cout << "person无参构造函数的调用" << endl;
// }
// person(int a)//有参
// {
// age = a;
// cout << "person有参构造函数的调用" << endl;
// }
// //析构函数
// ~person()
// {
// cout << "person析构函数的调用" << endl;
// }
// //拷贝构造函数
// person(const person& p)
// {
// //将传入的人身上所有属性拷贝到我的身上
// age = p.age;
// cout << "person有参拷贝函数的调用" << endl;
//
// }
// int age;
//};
//
调用构造函数
//void test01()
//{
// //1.括号法
// //person p1;//默认构造函数的调用
// //person p2(10);//有参构造函数的调用
// //person p3(p2);//拷贝构造函数的调用
//
// //注意事项1
// //调用默认构造函数时不要加()
// //因为下面这行代码,编译器会认为是一个函数的声明,不会认为在创建对象
// //person p1();
// //void func();
// //cout << "p2的年龄为:" << p2.age << endl;
// //cout << "p3的年龄为:" << p3.age << endl;
//
// //2.显示法
// //person p1;//无参构造
// //person p2 = person(10);//有参构造
// //person p3 =person(p2);//拷贝构造
//
// //person(10);//匿名对象 特点:当前行执行结束后,系统会立即回收掉匿名对象
// //cout << "aaaaaa" << endl;
//
// //注意事项2
// //不要利用拷贝构造函数,初始化匿名对象,编译器会认为person(p3)==person p3;
// //person(p3);//编译器误以为是对象声明,产生重定义的错误
//
// //3.隐式转换法
// person p4 = 10;//等价于 person p4=person(10);
// person p5 = p4;//拷贝构造
//}
//
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
/**********************3.拷贝构造函数的调用时机*****************************************/
//#include<iostream>
//using namespace std;
//
//class person
//{
//public:
// //无参构造函数
// person()
// {
// cout << "person默认构造函数的调用" << endl;
// }
// //有参构造函数
// person(int age)
// {
// cout << "person有参构造函数的调用" << endl;
// m_age = age;
// }
// //拷贝函数
// person(const person& p)
// {
// cout << "person拷贝构造函数的调用" << endl;
// m_age = p.m_age;
// }
//
// //析构函数
// ~person()
// {
// cout << "person析构函数的调用" << endl;
// }
// int m_age;
//
//};
//
//
C++中拷贝构造函数的调用时机
1.使用一个已经创建完毕的对象来初始化一个新对象
//void test01()
//{
// person p1(20);
// person p2(p1);
// cout << "p2的年龄为:" << p2.m_age<<endl;
//}
//
2.值传递方式给函数参数传值
//void dowork(person p)
//{}
//
//void test02()
//{
// person p;
// dowork(p);
//
//}
3.以值方式返回局对象
//person dowork2()
//{
// person p1;
// cout << (int*)&p1 << endl;
// return p1;
//}
//void test03()
//{
// person p = dowork2();
// cout << (int*)&p << endl;
//}
//
//
//
//int main()
//{
// //test01();
// //test02();
// test03();
// system("pause");
// return 0;
//}
/**********************4.构造函数调用规则*****************************************/
//#include<iostream>
//using namespace std;
//
默认情况 C++编译器至少给一个类添加3个函数
1.默认构造函数(无参,函数体为空)(空实现)
2.默认析构函数(无参,函数体为空)(空实现)
3.默认拷贝构造函数,对属性进行值拷贝(值拷贝)
//
构造函数的调用规则
用户定义有参构造函数,C++不提供默认无参构造函数,但是提供默认拷贝构造函数
用户定义拷贝构造函数,C++不会再提供其他的构造函数
//class person
//{
//
//public:
// //默认构造函数
// /*person()
// {
// cout << "person的默认构造函数调用" << endl;
// }*/
// 有参构造函数
// //person(int age)
// //{
// // cout << "person的有参构造函数调用" << endl;
// // m_age = age;
// //}
// //拷贝构造函数
// person(const person &p)
// {
// cout << "person的拷贝构造函数调用" << endl;
// m_age = p.m_age ;
// }
// //析构函数
// ~person()
// {
// cout << "person的析构函数调用" << endl;
// }
// int m_age;
//};
//
void test01()
{
person p;//无参构造
p.m_age = 18;
person p2(p);//拷贝构造函数
cout << "p2的年龄为:" << p2.m_age << endl;
}
//
//void test02()
//{
// person p(28);//调用有参构造函数
// person p2(p);//拷贝构造函数
// cout << "p2的年龄为:" << p2.m_age << endl;
//}
//
//
//int main()
//{
// //test01();
// test02();
// system("pause");
// return 0;
//}
/**********************5.深拷贝与浅拷贝*****************************************/
//#include<iostream>
//using namespace std;
//
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的重复释放堆区数据的问题
//class person
//{
//
//public:
// //默认构造函数
// person()
// {
// cout << "person的默认构造函数调用" << endl;
// }
// //有参构造函数
// person(int age,int height)
// {
// m_age = age;
// m_height = new int(height);//接受堆区的数据
// //堆区开辟的数据由程序员手动开辟,最后由程序员手动释放
// cout << "person的有参构造函数调用" << endl;
// }
//
// //自己写一个拷贝构造函数,解决浅拷贝带来的问题
// person(const person &p)
// {
// cout << "person的拷贝构造函数调用" << endl;
// m_age = p.m_age ;
// //m_height = p.m_height;//编译器默认实现的就是这行代码
// //深拷贝操作,重新开辟一个堆区空间
// m_height = new int(*p.m_height);
//
// }
//
// //析构函数
// ~person()
// {
// //析构代码,将堆区开辟的数据手动释放
// if (m_height != NULL)
// {
// delete m_height;//删除堆区数据
// m_height = NULL;//指针置空,防止出现野指针
// }
// cout << "person的析构函数调用" << endl;
// }
// int m_age;//年龄
// int* m_height;//将身高数据开辟到堆区
//};
//
//void test01()
//{
// person p1(18,160);//有参构造函数的调用
// cout << "p1的年龄为:" <<p1.m_age <<" 身高为:"<<*p1.m_height << endl;
// person p2(p1);//拷贝构造函数的调用
// //如果利用编译器提供的拷贝构造函数,会做浅拷贝
// //浅拷贝问题:堆区内存重复释放
// //浅拷贝问题要用深拷贝来解决
//
// cout << "p2的年龄为:" << p2.m_age <<" 身高为:" << *p2.m_height << endl;
//}
//
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
/**********************6.初始化列表*****************************************/
//C++提供初始化语法列表,来初始化属性
//#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(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(30,20,10);
// cout << "m_a=" << p.m_a << endl
// << "m_b=" << p.m_b << endl
// << "m_c=" << p.m_c << endl;
//}
//
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
/**********************7.类对象作为类成员*****************************************/
//#include<iostream>
//#include<string>
//using namespace std;
C++中的一个成员可以是另一个类的成员,称该成员为对象成员
//
手机类
//class phone
//{
//public:
// phone(string pname)//构造函数初始化手机名
// {
// m_pname = pname;
// cout << "phone的构造函数调用" << endl;
// }
// ~phone()
// {
// cout << "phone的析构函数调用" << endl;
// }
// string m_pname;
//};
人类
//class person
//{
//public:
// //构造函数赋予初值
// //phone m_phone=pname;//隐式转化法
// person(string name, string pname):m_name(name),m_phone(pname)
// {
// cout << "person的构造函数调用" << endl;
// }
// ~person()
// {
// cout << "person的析构函数调用" << endl;
// }
// //姓名
// string m_name;
// //手机
// phone m_phone;
//};
//
当其他类对象作为本类成员,构造的时候先构造类对象,再构造自身
析构的顺序与构造相反(栈的顺序—先进后出)
//void test01()
//{
// person p("李四","苹果MAXPRO");
// cout << p.m_name << "拿着" << p.m_phone.m_pname << "手机" << endl;
//}
//int main()
//{
// test01();
// system("pause");
// return 0;
//}
/**********************8.静态成员变量*****************************************/
//静态成员:在成员变量和成员函数前加上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;//类外初始化
//int person::m_b = 200;//类外初始化
//
//void test01()
//{
// person p;
// //100
// cout << p.m_a << endl;
//
// person p2;
// p2.m_a = 200;
// //200
// cout << p.m_a << endl;
//}
//
//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;
//}
/**********************8.静态成员函数*****************************************/
#include<iostream>
using namespace std;
//静态成员函数
/*
所有对象共享一个函数
静态成员函数只能访问静态成员变量
*/
class person
{
public:
//静态成员函数
static void func()
{
m_A = 100;//静态成员函数 可以访问 静态成员变量
//m_B = 200;//静态成员函数 不可以访问 非静态成员变量//无法区分是哪一个对象的m_B属性
cout << "static void func()调用" << endl;
}
//静态成员变量
static int m_A;//类内声明
//非静态成员变量——只能通过创建一个对象来访问
int m_B;
//静态成员函数也是有访问权限的
private:
static void func2()
{
cout << "static void func2()调用" << endl;
}
};
int person::m_A = 0;//类外初始化
//静态成员函数的两种访问方式
void test01()
{
//1.通过对象访问
person p;
p.func();
//2.通过类名访问
person::func();
//person::func2();//类外访问不到私有的静态成员函数
}
int main()
{
test01();
system("pause");
return 0;
}