一、类和对象
1.1面向对象编程介绍
使用类和对象来完成特定的功能的集合,通过每个对象来管理自己的数据和方法。
用到一个关键词:class
超强版的struct :类
1.2类和对象
1)c++中的类是class,可以看成是C语言中的struct的超强版本。结构体是一种构造类型,可以包含若干成员,类也一样,除了struct基本功能之外,类还有新增权限,
2)类的使用说明
1>类和struct一样,定义结尾需要加; 他是类的一部分,表示类定义结束,不能省略。
2>类也是一种构造类型,本身不占用内存空间,内存空间的计算方式和struct差不多。
3>对象成员的访问方式和struct一样,通过.或者->来访问。
4>类中的函数的作用范围由类来决定,作用范围可能是某个命名空间。
#include <iostream>
using namespace std;
struct Student //结构体默认是共有的
{
int age;
char *name;
};
class Student1 //类默认是私有的
{
public: //共有权限
int age;
char *name;
void print()
{
cout<<"age = "<<age<<"name = "<<name<<endl;
}
};
int main(int argc,char const *argv[] )
{
Student1 s1;
s1.age = 19;
s1.name = "xiaoming";
s1.print();
return 0;
}
1.3 访问控制
访问级别:共有权限(public),保护权限(protect),私有权限(private)。
public :共有属性, 凡是在它下面定义的属性或者方法,类的内部和外部都可以访问。
protect:保护属性,凡是在它下面定义的属性或者方法,类的内部和继承的内部可以访问,外部不可以访问。
private:私有属性,凡是在它下面定义的属性或者方法,类的内部可以访问,它的继承和外部都不可以访问。
#include <iostream>
using namespace std;
class Test
{
public: //公有属性,类的内部和外部都可以访问
int b;
void f2(){}
protected: //保护属性,类的内部和类的继承中访问
int c;
void f3(){}
private: //私有属性,类的内部可以访问
int a;
void f1(){}
};
int main(int argc, char const *argv[])
{
Test t1;
//t1.a = 1; //私有成员无法在类的外部访问
t1.b = 2;
//t1.c = 3;
return 0;
}
**注意:1.public ,protected, private的关键词可以出现多次,有效范围是在下一个关键词出现之前
2.struct默认是公有属性,class默认是私有属性**
#include <iostream>
using namespace std;
class Circle
{
private:
int m_r;
double m_s;
public:
void SetR(int r) //用共有来操作私有属性
{
m_r = r;
}
double Gets()
{
m_s = 3.14 * m_r * m_r;
return m_s;
}
};
int main(int argc, char const *argv[])
{
Circle c1; //创建对象
c1.SetR(2);
cout<<"面积 = "<<c1.Gets()<<endl;
return 0;
}
1.4类的实际使用(分文件使用)
设计一个立方体类Cube,求出立方体的面积和体积,并判断两个立方体是否相等
要求:私有成员变量(属性):长length,宽wide, 高hight
成员函数(方法):求面积和体积
全局函数:判断两个立方体是否相等
//头文件
#ifndef _CUBE_H_
#define _CUBE_H_
#include <iostream>
using namespace std;
class Cube
{
private:
int m_length;
int m_wide;
int m_hight;
public:
int GetS(); //得到面积
int GetV(); //得到体积
void SetS(int length,int wide,int hight); //设置长宽高
void SetV(int length,int wide,int hight);
int Getlength();
int GetWide();
int Gethight();
};
bool CubeIsEqu(Cube c1, Cube c2); //判断是否相等
#endif
#include "Cube.h"
//功能实现
void Cube::SetS(int length, int wide, int hight)
{
m_length = length;
m_wide = wide;
m_hight = hight;
}
void Cube::SetV(int length, int wide, int hight)
{
m_length = length;
m_wide = wide;
m_hight = hight;
}
int Cube::GetS()
{
return m_length * m_wide * m_hight;
}
int Cube::GetV()
{
return (2 *(m_length * m_wide + m_length * m_hight + m_wide * m_hight));
}
int Cube::Getlength()
{
return m_length;
}
int Cube::GetWide()
{
return m_wide;
}
int Cube::Gethight()
{
return m_hight;
}
bool CubeIsEqu(Cube c1, Cube c2)
{
if(c1.Getlength() == c2.Getlength() && c1.GetWide() == c2.GetWide() && c1.Gethight() == c2.Gethight())
{
return true;
}
else
{
return false;
}
}
#include "Cube.h"
int main(int argc, char const *argv[])
{
Cube c1;
Cube c2;
c1.SetS(3,4,5);
c2.SetS(3,5,4);
cout<<"c1面积 = "<<c1.GetS()<<endl;
cout<<"c2面积 = "<<c2.GetS()<<endl;
cout<<"c1体积 = "<<c1.GetV()<<endl;
cout<<"c2体积 = "<<c2.GetV()<<endl;
if(CubeIsEqu(c1,c2))
{
cout<<"c1 = c2"<<endl;
}
else
{
cout<<"c1 != c2"<<endl;
}
return 0;
}
练习:面向对象编程实例
要求:设计一个圆形类和一个点类,计算点在员外还是圆内,即求点和圆的关系
1)点:属性: 横坐标和纵坐标
方法:点和点之间的距离计算
2)圆:属性:圆心,半径
方法:1.设计圆心和半径
2.判断点和园的关系
#ifndef CIRCLE_H_
#define CIRCLE_H_
#include <iostream>
using namespace std;
class Point //点
{
private:
int m_x;
int m_y; //横纵坐标
public:
void SetXY(int x,int y); //输入点的坐标
int Distance(Point &p); //距离
int GetX();
int GetY();
};
class Circle //圆
{
private:
int m_r; //半径
Point m_center; //圆心
public:
void SetC(int x, int y, int m_r);
bool judge(Point &p);
};
//bool Circle::judge(Point &p);
#endif
#include "circle.h"
void Point::SetXY(int x, int y)
{
m_x = x;
m_y = y;
}
int Point::GetX()
{
return m_x;
}
int Point::GetY()
{
return m_y;
}
void Circle::SetC(int x,int y,int m)
{
m_center.SetXY(x,y);
m_r = m; //半径
}
int Point::Distance(Point &p)
{
int dis = (p.GetX() - m_x) * (p.GetX() -m_x) + (p.GetY() - m_y) * (p.GetY() - m_y);
return dis;
}
bool Circle::judge(Point &p)
{
if(p.Distance(m_center) <= m_r * m_r)
{
return true;
}
else
{
return false;
}
}
#include "circle.h"
int main(int argc, char const *argv[])
{
Point p1;
p1.SetXY(0,0);
Circle c1;
c1.SetC(0,0,1);
if(c1.judge(p1))
{
cout<<"点在圆内或者圆上"<<endl;
}
else
{
cout<<"点在园外"<<endl;
}
return 0;
}
1.5 对象的构造和析构
1)构造函数:是C++中一种特殊的成员函数,它的名字和类名相同,没有返回值,不需要用户显示调用,而是在创建对象的时候自动执行,这种特殊的函数称为构造函数。
注意:1.构造函数名必须与类同名。2.构造函数不能有返回值。 3.构造函数在定义的时候自动调用,不需要手动调用。
#include <iostream>
using namespace std;
class Array
{
private:
int *data; //数组的起始地址
int size; //数组大小
public:
Array(); //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
void SetVal(int Index,int val);
int GetVal(int Index);
~Array(); //析构函数
};
Array ::Array() //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
{
cout<<"array的无参构造函数"<<endl;
size = 5;
data = (int *)malloc(sizeof(int)*size);
}
void Array::SetVal(int Index,int val)
{
data[Index] = val;
}
int Array::GetVal(int Index)
{
return data[Index];
}
Array::~Array()
{
cout<<"Array的析构函数"<<endl;
if(data != NULL)
{
free(data);
}
}
int main(int argc,char const *argv[])
{
Array a1;
for(int i = 0; i < 5; i++)
{
a1.SetVal(i,i+1);
}
for(int i = 0; i < 5; i++)
{
cout<<a1.GetVal(i)<<" ";
}
cout<<endl;
return 0;
}
2.构造函数的重载和调用
和普通函数一样,构造函数也是允许重载的,也就是说,一个类可以有多个构造函数,在创建对象时根据传递的实参来判断调用哪一个函数
#include <iostream>
using namespace std;
class Array
{
private:
int *data; //数组的起始地址
int size; //数组大小
public:
Array(); //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
Array(int s); //有参构造函数
Array(int s,int z); //有两个参数的构造函数
Array(const Array &a);
void SetVal(int Index,int val);
int GetVal(int Index);
~Array(); //析构函数
};
Array::Array(int s) //有参构造函数
{
cout<<"size = "<<s<<endl;
size = s;
data = (int *)malloc(sizeof(int) * size);
cout<<"有一个参数的构造函数"<<endl;
}
Array::Array(int s,int z) //有两个参数的构造函数
{
size = s;
data = (int *)malloc(sizeof(int) * size);
cout<<"有一个参数的构造函数"<<endl;
}
Array::Array(const Array &a)
{
cout<<"Array的拷贝构造函数"<<endl;
}
Array ::Array() //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
{
cout<<"array的无参构造函数"<<endl;
size = 5;
data = (int *)malloc(sizeof(int)*size);
}
void Array::SetVal(int Index,int val)
{
data[Index] = val;
}
int Array::GetVal(int Index)
{
return data[Index];
}
Array::~Array()
{
cout<<"Array的析构函数"<<endl;
if(data != NULL)
{
free(data);
}
}
int main(int argc,char const *argv[])
{
Array a1;
for(int i = 0; i < 5; i++)
{
a1.SetVal(i,i+1);
}
for(int i = 0; i < 5; i++)
{
cout<<a1.GetVal(i)<<" ";
}
cout<<endl;
cout<<"***************"<<endl;
Array a2 = 10;
for(int i = 0; i < 10; i++)
{
a2.SetVal(i,i+100);
}
for(int i = 0; i < 10; i++)
{
cout<<a2.GetVal(i)<<" ";
}
cout<<endl;
cout<<"***************"<<endl;
Array a3(10,8);
Array a4(a1);
return 0;
}
3.拷贝构造函数的调用时机
1)用一个对象初始化另一个对象的时候
2)当函数的参数是一个类的对象
3)当函数返回一个对象的引用
#include <iostream>
using namespace std;
class Array
{
private:
int *data; //数组的起始地址
int size; //数组大小
public:
Array(); //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
Array(const Array &a);
void SetVal(int Index,int val);
int GetVal(int Index);
~Array(); //析构函数
};
Array::Array(const Array &a)
{
cout<<"Array的拷贝构造函数"<<endl;
}
Array ::Array() //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
{
cout<<"array的无参构造函数"<<endl;
size = 5;
data = (int *)malloc(sizeof(int)*size);
}
void Array::SetVal(int Index,int val)
{
data[Index] = val;
}
int Array::GetVal(int Index)
{
return data[Index];
}
Array::~Array()
{
cout<<"Array的析构函数"<<endl;
if(data != NULL)
{
free(data);
}
}
void print(Array a) //当函数的形参是一个对象 array a = a1;
{
a.GetVal(1);
}
Array& fun() //函数返回值是一个对象
{
Array a1;
return a1;
}
int main(int argc,char const *argv[])
{
Array a1;
for(int i = 0; i < 5; i++)
{
a1.SetVal(i,i+1);
}
for(int i = 0; i < 5; i++)
{
cout<<a1.GetVal(i)<<" ";
}
cout<<endl;
cout<<"***************"<<endl;
Array a2 = fun();
return 0;
}
4.深拷贝
#include <iostream>
using namespace std;
class Array
{
private:
int *data; //数组的起始地址
int size; //数组大小
public:
Array(); //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
Array(const Array &a);
void SetVal(int Index,int val);
int GetVal(int Index);
~Array(); //析构函数
};
Array::Array(const Array &a) //深拷贝
{
cout<<"Array的拷贝构造函数"<<endl;
size = a.size;
data =(int *)malloc(sizeof(int) * size);
for(int i = 0; i < size; i++)
{
data[i] = a.data[i];
}
}
Array ::Array() //无参构造函数,函数名和类名一样,没有返回值,完成对象的初始化操作
{
cout<<"array的无参构造函数"<<endl;
size = 5;
data = (int *)malloc(sizeof(int)*size);
}
void Array::SetVal(int Index,int val)
{
data[Index] = val;
}
int Array::GetVal(int Index)
{
return data[Index];
}
Array::~Array()
{
cout<<"Array的析构函数"<<endl;
if(data != NULL)
{
free(data);
}
}
void print(Array a) //当函数的形参是一个对象 array a = a1;
{
a.GetVal(1);
}
int main(int argc,char const *argv[])
{
Array a1;
for(int i = 0; i < 5; i++)
{
a1.SetVal(i,i+1);
}
for(int i = 0; i < 5; i++)
{
cout<<a1.GetVal(i)<<" ";
}
cout<<endl;
cout<<"***************"<<endl;
Array a2(a1); //用一个对象初始化另一个对象
return 0;
}
1.7 析构函数
析构函数会在对象销毁时自动调用,析构函数没有返回值,没有参数,不能重载。
1)匿名对象
```cpp
#include <iostream>
using namespace std;
class Demo
{
public:
Demo()
{
cout<<"Demo的无参构造函数"<<endl;
}
~Demo()
{
cout<<"Demo的析构函数"<<endl;
}
};
int main(int argc, char const *argv[])
{
Demo(); //匿名对象,本行执行完立即被释放
Demo();
cout<<"*******************"<<endl;
return 0;
}
1)C++中malloc 和 new 使用
```cpp
#include <iostream>
using namespace std;
class Demo
{
public:
Demo()
{
cout<<"Demo的无参构造函数"<<endl;
}
Demo(int a, int b)
{
cout<<"Demo的两个参数的构造函数"<<endl;
}
~Demo()
{
cout<<"Demo的析构函数"<<endl;
}
};
int main(int argc, char const *argv[])
{
Demo *pd = (Demo *)malloc(sizeof(Demo)); //在堆空间申请对象那个,malloc不会自动调用构造和析构函数
if(pd == NULL)
{
cout<<"malloc failed"<<endl;
}
free(pd);
Demo *pd2 = new Demo; //申请堆空间,自动调用构造函数
delete pd2; //释放空间,自动调用析构函数
Demo *pd3 = new Demo(100,200);
delete pd3;
return 0;
}