01 面向对象设计案例-立方体案例
分别用全局函数和成员函数判断两个立方体是否相等
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
/*
设计立方体(Cube),
求出立方体面积(2*a*b+2*a*c+2*b*c)和体积(a*b*c)
分别用全局函数和成员函数判断两个立方体是否相等
*/
class Cube
{
public:
//设置长
void setLong(int l)
{
Long = l;
}
//获取长
int getLong()
{
return Long;
}
//设置宽
void setWidth(int w)
{
Width = w;
}
//获取宽
int getWidth()
{
return Width;
}
//设置高
void setHeight(int h)
{
Height = h;
}
//获取高
int getHeight()
{
return Height;
}
//求立方体的面积
void getCubeS()
{
int s = 2 * Long * Width + 2 * Long * Height + 2 * Width * Height;
cout << "立方体的面积为: " << s << endl;
}
//求立方体的体积
void getCubeV()
{
int v = Long * Width * Height;
cout << "立方体的体积为: " << v << endl;
}
//通过成员函数来判断两个立方体是否相等
bool compareCubeByClass(Cube& cub)
{
//if (NULL == &cub)
//{
// return NULL;
//}
bool ret = Long == cub.getLong() && Width == cub.getWidth() && Height == cub.getHeight();
return ret;
}
private:
int Long;
int Width;
int Height;
};
//通过全局函数来判断两个立方体是否相等
bool compareCube(Cube& c1, Cube& c2)
{
//if (NULL == &c1 || NULL == &c2)
//{
// return NULL;
//}
if (c1.getLong() == c2.getLong() && c1.getWidth() == c2.getWidth() && c1.getHeight() == c2.getHeight())
{
return true;
}
else
{
return false;
}
}
void test01()
{
Cube c1;
Cube c2;
c1.setLong(10);
c1.setHeight(10);
c1.setWidth(10);
c2.setLong(10);
c2.setHeight(11);
c2.setWidth(10);
//获得c2的面积和体积
c2.getCubeS();
c2.getCubeV();
//通过成员函数来判断立方体是否相等
bool ret1 = c1.compareCubeByClass(c2);
if (ret1)
{
cout << "通过成员函数判断:两个立方体相等!" << endl;
}
if (!ret1)
{
cout << "通过成员函数判断:两个立方体不相等!" << endl;
}
bool ret2 = compareCube(c1, c2);
if (ret2)
{
cout << "通过全局判断:两个立方体相等!" << endl;
}
if (!ret2)
{
cout << "通过全局判断:两个立方体不相等!" << endl;
}
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
02 面向对象设计案例-点和圆的关系
不分文件编写
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
/*
设计一个圆形类(AdvCircle),和一个点类(Point),计算点和圆的关系。
加入圆心坐标为x0,y0,半径为r,点的坐标x1,y1
*/
//创建一个点类
class Point {
public:
void setX(int x)
{
m_X = x;
}
int getX()
{
return m_X;
}
void setY(int y)
{
m_Y = y;
}
int getY()
{
return m_Y;
}
private:
int m_X;
int m_Y;
};
//创建一个圆类
class Circle {
public:
//设置半径
void setR(int r)
{
R = r;
}
//获取半径
int getR()
{
return R;
}
//设置圆心
void setCenter(Point& p)
{
//Center.setX(p.getX());
//Center.setY(p.getY());
Center = p;
}
//获取圆心
Point getCenter()
{
return Center;
}
//在圆的内部判断点和圆的关系
void isInCircleByClass(Point& p)
{
//获取圆心和点距离的平方
int distance = (Center.getX() - p.getX()) * (Center.getX() - p.getX()) + (Center.getY() - p.getY()) * (Center.getY() - p.getY());
//获取半径的平方
int r_2 = R * R;
if (distance > r_2)
{
cout << "利用成员函数判断:点在圆的外部" << endl;
}
else if (distance == r_2)
{
cout << "利用成员函数判断:点在圆上" << endl;
}
else
{
cout << "利用成员函数判断:点在圆的内部" << endl;
}
}
private:
int R;
Point Center;
};
//利用全局函数来判断点和圆的关系
void isInCircle(Circle& c, Point& p)
{
//获取圆心和点距离的平方
int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) + (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
//获取半径的平方
int r_2 = c.getR() * c.getR();
if (distance > r_2)
{
cout << "利用全局函数判断:点在圆的外部" << endl;
}
else if (distance == r_2)
{
cout << "利用全局函数判断:点在圆上" << endl;
}
else
{
cout << "利用全局函数判断:点在圆的内部" << endl;
}
}
void test01()
{
Point p1;
p1.setX(10);
p1.setY(8);
Circle c1;
Point center;
center.setX(10);
center.setY(0);
c1.setR(10);
c1.setCenter(center);
//利用全局函数判断点和圆的位置关系
isInCircle(c1, p1);
//利用成员函数判断点和圆的位置关系
c1.isInCircleByClass(p1);
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
分文件编写
point.h:
//创建一个点类
class Point {
public:
void setX(int x);
int getX();
void setY(int y);
int getY();
private:
int m_X;
int m_Y;
};
point.cpp:
#include "point.h"
void Point::setX(int x)
{
m_X = x;
}
int Point::getX()
{
return m_X;
}
void Point::setY(int y)
{
m_Y = y;
}
int Point::getY()
{
return m_Y;
}
circle.h:
#include<iostream>
#include"point.h"
using namespace std;
//创建一个圆类
class Circle {
public:
//设置半径
void setR(int r);
//获取半径
int getR();
//设置圆心
void setCenter(Point& p);
//获取圆心
Point getCenter();
//在圆的内部判断点和圆的关系
void isInCircleByClass(Point& p);
private:
int R;
Point Center;
};
circle.cpp:
#include"circle.h"
//设置半径
void Circle::setR(int r)
{
R = r;
}
//获取半径
int Circle::getR()
{
return R;
}
//设置圆心
void Circle::setCenter(Point& p)
{
//Center.setX(p.getX());
//Center.setY(p.getY());
Center = p;
}
//获取圆心
Point Circle::getCenter()
{
return Center;
}
//在圆的内部判断点和圆的关系
void Circle::isInCircleByClass(Point& p)
{
//获取圆心和点距离的平方
int distance = (Center.getX() - p.getX()) * (Center.getX() - p.getX()) + (Center.getY() - p.getY()) * (Center.getY() - p.getY());
//获取半径的平方
int r_2 = R * R;
if (distance > r_2)
{
cout << "利用成员函数判断:点在圆的外部" << endl;
}
else if (distance == r_2)
{
cout << "利用成员函数判断:点在圆上" << endl;
}
else
{
cout << "利用成员函数判断:点在圆的内部" << endl;
}
}
面向对象设计案例-点和圆的关系.cpp:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include"circle.h"
#include"point.h"
/*
设计一个圆形类(AdvCircle),和一个点类(Point),计算点和圆的关系。
加入圆心坐标为x0,y0,半径为r,点的坐标x1,y1
*/
//利用全局函数来判断点和圆的关系
void isInCircle(Circle& c, Point& p)
{
//获取圆心和点距离的平方
int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) + (c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
//获取半径的平方
int r_2 = c.getR() * c.getR();
if (distance > r_2)
{
cout << "利用全局函数判断:点在圆的外部" << endl;
}
else if (distance == r_2)
{
cout << "利用全局函数判断:点在圆上" << endl;
}
else
{
cout << "利用全局函数判断:点在圆的内部" << endl;
}
}
void test01()
{
Point p1;
p1.setX(10);
p1.setY(8);
Circle c1;
Point center;
center.setX(10);
center.setY(0);
c1.setR(10);
c1.setCenter(center);
//利用全局函数判断点和圆的位置关系
isInCircle(c1, p1);
//利用成员函数判断点和圆的位置关系
c1.isInCircleByClass(p1);
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
03 对象的初始化和清理
构造函数的写法:
1.没有返回值,不写void,和类名相同,可以发生重载(可以有参数)
2.构造函数由编译器自动调用,而不是手动,而且只会调用一次
析构函数的写法:
与类名相同,类名前面加一个符号"~",也没有返回值,不写void,不可以有参数
如果程序员没有提供构造函数和析构函数,系统会默认提供,空实现
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
// 构造函数的写法
//没有返回值,不写void,和类名相同,可以发生重载(可以有参数)
//构造函数由编译器自动调用,而不是手动,而且只会调用一次
Person()
{
cout << "调用构造函数" << endl;
}
//析构函数的写法
//与类名相同,类名前面加一个符号"~",也没有返回值,不写void,不可以有参数
~Person()
{
cout << "调用析构函数" << endl;
}
};
void test01()
{
Person p1;//默认调用了构造和析构,如果没有编写的话是系统提供的两个空实现的函数
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
04 构造函数的分类及调用
构造函数的分类:
按照参数进行分类:无参构造函数(默认构造函数) 有参构造函数
按照类型进行分类:普通构造函数 拷贝构造函数
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()//默认、无参构造函数
{
cout << "默认构造函数调用" << endl;
}
Person(int a)//有参构造函数
{
cout << "有参构造函数调用" << endl;
}
//拷贝构造函数
Person(const Person& p) //拷贝构造,不让修改,加const
{
m_Age = p.m_Age;
cout << "拷贝构造函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
int m_Age = 0;
};
void test01()
{
//构造函数调用方式
//括号法调用
Person p1(1);//有参构造函数
p1.m_Age = 10;
Person p2(p1);//拷贝构造函数
cout << "p2的年龄: " << p2.m_Age << "岁" << endl;
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
匿名对象特点:如果编译器发现了对象是匿名的,那么在这行代码结束后就释放这个对象
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()//默认、无参构造函数
{
cout << "默认构造函数调用" << endl;
}
Person(int a)//有参构造函数
{
cout << "有参构造函数调用" << endl;
}
//拷贝构造函数
Person(const Person& p) //拷贝构造,不让修改,加const
{
m_Age = p.m_Age;
cout << "拷贝构造函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
int m_Age = 0;
};
void test01()
{
//构造函数调用方式
//括号法调用
Person p1(1);//有参构造函数
p1.m_Age = 10;
Person p2(p1);//拷贝构造函数
cout << "p2的年龄: " << p2.m_Age << "岁" << endl;
Person p3;//默认构造函数 不要加小括号
//Person p3();//编译器认为这行是函数的声明
//显示法调用
Person p4 = Person(100);
Person p5 = Person(p4);
Person(100);//叫匿名对象
//匿名对象特点:如果编译器发现了对象是匿名的,那么在这行代码结束后就释放这个对象
cout << "aaaa" << endl;
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
总结:
无参构造函数的写法和调用:
Person(){}
Person p1;//注意不能写Person p1(); 因为编译器会认为这是函数声明
有参函数写法和调用:
Person(int a){}
Person p2(10);//或者
Person p2 = Person(10);
Person(10);//匿名对象,执行当前行后就会释放这个对象
拷贝构造函数写法和调用:
Person(const Person& p){}
Person p1(p2);//或者
Person p1 = Person(p2)
不能用拷贝构造函数初始化匿名对象
如果写成Person(p1);这种写法等价于 Person p1
Person p = 100;//隐式类型转换,相当于 Person p = Person(100)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//分类
//按照参数进行分类:无参构造函数(默认构造函数) 有参构造函数
//按照类型进行分类:普通构造函数 拷贝构造函数
/*
总结:
无参构造函数的写法和调用:
Person(){}
Person p1;//注意不能写Person p1(); 因为编译器会认为这是函数声明
有参函数写法和调用:
Person(int a){}
Person p2(10);//或者
Person p2 = Person(10);
Person(10);//匿名对象,执行当前行后就会释放这个对象
拷贝构造函数写法和调用:
Person(const Person& p){}
Person p1(p2);//或者
Person p1 = Person(p2)
不能用拷贝构造函数初始化匿名对象
如果写成Person(p1);这种写法等价于 Person p1
Person p = 100;//隐式类型转换,相当于 Person p = Person(100)
*/
class Person
{
public:
Person()//默认、无参构造函数
{
cout << "默认构造函数调用" << endl;
}
Person(int a)//有参构造函数
{
cout << "有参构造函数调用" << endl;
}
//拷贝构造函数
Person(const Person& p)
{
m_Age = p.m_Age;
cout << "拷贝构造函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
int m_Age = 0;
};
void test01()
{
//构造函数调用方式
//括号法调用
Person p1(1);//有参构造函数
p1.m_Age = 10;
Person p2(p1);//拷贝构造函数
cout << "p2的年龄: " << p2.m_Age << "岁" << endl;
Person p3;//默认构造函数 不要加小括号
//Person p3();//编译器认为这行是函数的声明
//显示法调用
Person p4 = Person(100);
Person p5 = Person(p4);
//Person(100);//叫匿名对象
//匿名对象特点:如果编译器发现了对象是匿名的,那么在这行代码结束后就释放这个对象
//不能用拷贝构造函数初始化匿名对象
//Person(p5);//如果写成左值,编译器认为你写成了Person p5,对象的声明;写成右值的话是可以的
Person p6 = Person(p5);
//不常用的用法(影响阅读性)
Person p7 = 100;//相当于写了person p7 = Person(100),隐式类型转换
Person p8 = p7;//相当于写了 Person p8 = Person(p7)
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
05 拷贝构造函数的调用时机
1.用一个已经创建好的对象来初始化新的对象
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "默认构造函数调用" << endl;
}
Person(int a)
{
cout << "有参构造函数调用" << endl;
}
Person(const Person& p)
{
m_Age = p.m_Age;
cout << "拷贝构造函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
int m_Age;
};
//拷贝构造函数的调用时机
//1、用一个已经创建好的对象来初始化新的对象
void test01()
{
Person p1;
p1.m_Age = 10;
Person p2(p1);
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
2.以值传递的方式给函数参数传值
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "默认构造函数调用" << endl;
}
Person(int a)
{
cout << "有参构造函数调用" << endl;
}
Person(const Person& p)
{
m_Age = p.m_Age;
cout << "拷贝构造函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
int m_Age;
};
//2、以值传递的方式给函数参数传值
void doWork(Person p1)
{
}
void test02()
{
Person p;
p.m_Age = 10;
doWork(p);
}
int main(void)
{
test02();
system("pause");
return EXIT_SUCCESS;
}
3.以值的方式返回局部对象
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "默认构造函数调用" << endl;
}
Person(int a)
{
cout << "有参构造函数调用" << endl;
}
Person(const Person& p)
{
m_Age = p.m_Age;
cout << "拷贝构造函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
int m_Age;
};
//3、以值的方式返回局部对象
Person doWork2()
{
Person p1;
p1.m_Age = 10;
cout << "aaa" << endl;
return p1;
}
void test03()
{
Person p1 = doWork2();
cout << "bbb" << endl;
}
/Release模式下会对代码进行优化
//Person p; //不调用默认构造
//doWork2(p);
//void doWork2(Person& p)
//{
// Person p1;//调用默认构造函数
//}
int main(void)
{
test03();
system("pause");
return EXIT_SUCCESS;
}
06 构造函数的调用规则
系统默认给一个类提供3个函数:默认构造、拷贝构造、析构函数
1.规则一:当我们提供了有参构造函数,那么系统就不会再给我们提供默认构造函数了
但是,系统会提供默认的拷贝构造函数,进行简单的值拷贝
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class myClass
{
public:
/*myClass()
{
cout << "默认构造函数调用" << endl;
}*/
myClass(int a)
{
cout << "有参构造函数调用" << endl;
}
/*myClass(const myClass& c)
{
m_A = c.m_A;
cout << "拷贝构造函数调用" << endl;
}*/
int m_A;
};
//系统默认给一个类提供3个函数:默认构造、拷贝构造、析构函数
//规则一:当我们提供了有参构造函数,那么系统就不会再给我们提供默认构造函数了
//但是,系统会提供默认的拷贝构造函数,进行简单的值拷贝
void test01()
{
myClass c1(1);
c1.m_A = 10;
myClass c2(c1);
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
2.规则二:当我们提供了拷贝构造,那么系统就不会提供其他构造了
//规则二:当我们提供了拷贝构造,那么系统就不会提供其他构造了
class myClass2
{
public:
/*myClass2()
{
cout << "默认构造函数调用" << endl;
}*/
/*myClass2(int a)
{
cout << "有参构造函数调用" << endl;
}*/
myClass2(const myClass& c)
{
m_A = c.m_A;
cout << "拷贝构造函数调用" << endl;
}
int m_A;
};
void test02()
{
//myClass2 c1;//会报错
}
07 深拷贝和浅拷贝
1. 浅拷贝
拷贝函数,系统会提供默认的拷贝函数,进行简单的值拷贝(浅拷贝)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person() {}
//初始化属性
Person(const char* name, int age)
{
m_Name = (char*)malloc(strlen(name) + 1);
strcpy(m_Name, name);
m_Age = age;
}
//拷贝函数,系统会提供默认的拷贝函数,进行简单的值拷贝(浅拷贝)
~Person()
{
if (m_Name != NULL)
{
free(m_Name);
m_Name = NULL;
}
}
char* m_Name;
int m_Age;
};
void test01()
{
/*char name[] = "xujie";
Person p1(name, 23);*/
Person p1("xujie", 23);
Person p2(p1);
cout << "p2的姓名:" << p2.m_Name << " p2的年龄:" << p2.m_Age << endl;
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
会报错:
浅拷贝原理:
2.深拷贝
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person() {}
//初始化属性
Person(const char* name, int age)
{
m_Name = (char*)malloc(strlen(name) + 1);
strcpy(m_Name, name);
m_Age = age;
}
//拷贝函数,系统会提供默认的拷贝函数,进行简单的值拷贝(浅拷贝)
//自己提供拷贝构造(深拷贝),原因是:简单的浅拷贝会使堆空间被是放两次,导致代码挂掉。
Person(const Person& p)
{
m_Name = (char*)malloc(strlen(p.m_Name) + 1);
strcpy(m_Name, p.m_Name);
m_Age = p.m_Age;
}
~Person()
{
if (m_Name != NULL)
{
free(m_Name);
m_Name = NULL;
}
}
char* m_Name;
int m_Age;
};
void test01()
{
/*char name[] = "xujie";
Person p1(name, 23);*/
Person p1("xujie", 23);
Person p2(p1);
cout << "p2的姓名:" << p2.m_Name << " p2的年龄:" << p2.m_Age << endl;
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
深拷贝原理:
08 初始化列表的基本使用
构造函数后面+:属性(参数),属性(参数)…
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
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;
}*/
//利用初始化列表来初始化数据
//构造函数后面+:属性(参数),属性(参数)...
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 p1(10, 20, 30);
cout << "p1的m_A为: " << p1.m_A << endl;
cout << "p1的m_B为: " << p1.m_B << endl;
cout << "p1的m_C为: " << p1.m_C << endl;
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
09 类对象作为成员
类对象作为类成员的时候,构造顺序先将类对象一一构造,然后构造自己,析构顺序是相反的
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class Phone
{
public:
Phone() {
cout << "手机的默认构造函数调用" << endl;
}
Phone(string name) :phoneName(name) {
cout << "手机的有参构造函数调用" << endl;
}
~Phone()
{
cout << "手机的析构函数调用" << endl;
}
string phoneName;
};
class Game
{
public:
Game() {
cout << "游戏的默认构造函数调用" << endl;
}
Game(string name) :gameName(name) {
cout << "游戏的有参构造函数调用" << endl;
}
~Game()
{
cout << "游戏的析构函数调用" << endl;
}
string gameName;
};
class Person
{
public:
Person()
{
cout << "人的默认构造函数调用" << endl;
}
Person(string name, string phoneName, string gameName) :personName(name), personsPhone(phoneName), personsGame(gameName)
{
cout << "人的有参构造函数调用" << endl;
}
~Person()
{
cout << "人的析构函数调用" << endl;
}
void playGame()
{
cout << personName << "用" << personsPhone.phoneName << "手机玩" << personsGame.gameName << "游戏!" << endl;
}
string personName;
Phone personsPhone;
Game personsGame;
};
//类对象作为类成员的时候,构造顺序先将类对象一一构造,然后构造自己,析构顺序是相反的
void test01()
{
Person p1("徐杰", "小米", "王者荣耀");
p1.playGame();
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
10 explicit关键字
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class myString
{
public:
myString() {}
myString(const char* str)
{
mStr = (char*)malloc(strlen(str) + 1);
strcpy(mStr, str);
}
//explicit关键字的用途就是防止隐式类型转换
explicit myString(int a)
{
mSize = a;
}
~myString()
{
if (mStr != NULL)
{
free(mStr);
mStr = NULL;
}
}
char* mStr;
int mSize;
};
void test01()
{
myString str = "abc";
myString str2(10);
//myString str3 = 10;//这种表达方式不明确,对代码的可读性产生不利影响
//隐式类型转换
//explicit关键字的用途就是防止隐式类型转换
}
int main(void)
{
system("pause");
return EXIT_SUCCESS;
}
11 new运算符使用
C语言的malloc动态分配内存和free释放内存存在如下问题:
1.程序员必须确定对象的长度
2.malloc返回一个void指针,C++不允许将void赋值给其他任何指针,必须强转
3.malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功
4.用户在使用对象之前必须记住对他初始化,构造函数不能显示调用初始化(构造函数由编译器调用),用户由可能忘记调用初始化函数。
1.当new创建一个对象时,它就在堆里为对象分配内存并调用构造函数完成初始化
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "默认函数调用" << endl;
}
Person(int a)
{
cout << "有参函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
};
void test01()
{
//Person p1;//栈区开辟
Person* p2 = new Person;//堆区开辟
//所有new出来的对象,都会返回该类型的指针
//malloc返回void* 类型的指针,还要强转
//malloc不会调用构造 而new会调用构造
//new 是运算符 malloc是系统提供的函数
//释放堆区空间
//delete配合new用,malloc配合free用
delete p2;
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
2.当用void* 接收new出的指针,会出现释放的问题
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "默认函数调用" << endl;
}
Person(int a)
{
cout << "有参函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
};
void test02()
{
void* p = new Person;
//当用void* 接收new出的指针,会出现释放的问题
//无法释放
delete p;
}
int main(void)
{
test02();
system("pause");
return EXIT_SUCCESS;
}
3.通过new开辟数组 ,一定会调用默认构造函数,所以一点定要提供默认构造函数
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "默认函数调用" << endl;
}
Person(int a)
{
cout << "有参函数调用" << endl;
}
~Person()
{
cout << "析构函数调用" << endl;
}
};
void test03()
{
//通过new开辟数组 一定会调用默认构造函数,所以一点定要提供默认构造函数
Person* pArray = new Person[10];
//在栈上开辟数组,可以指定有参构造
Person pArray2[2] = { Person(1),Person(2) };
//如果在new表达式中使用[],必须在相应的delete表达式中也使用[];
//如果在New表达式中不使用[],那么在相应的delete表达式中也一定不要使用[];
delete[] pArray;
}
int main(void)
{
test03();
system("pause");
return EXIT_SUCCESS;
}