C++构造析构
C++构造析构
目录
1.单个类说明
类的生命周期起始于构造函数,终止于析构函数.可以在栈(直接使用)上创建也可以在堆(new 产生)上创建,也可以限制允许在一种情况下创建. 其中构造函数可以重载(不同的参数匹配不同的构造,达到多态目的),析构不能重载(析构本身无参). 当创建一个类时c++会创建以下默认函数
- default构造函数 (无参构造函数)
- 拷贝构造函数 (由相同的类创建本类)
- =重载操作符函数 (本类已经存在,用于对本类进行重新赋值,默认生成左值复制和右值复制) 右值复制 c++11才有)
- 析构函数 (生命周期结束时调用)
- 移动构造函数 (c++11才有)
类的动态创建可以分为2步:第一步分配内存,第二步调用构造函数. 因此有二种不同的玩法:
- 玩法一(普通玩法):分配内存和调用构造一起 如:
class A{int m;};
A *pa = new A(); //堆上构造
delete pa; //释放析构
- 玩法二(高级玩法):先分配内存 然后再调用构造函数 如:
class A{int m;};
A *pa = (A *)malloc(sizeof(A) *2); //先分配内存(可以分配很多)
new(&pa[0]) A(); //只调用构造(如果有内存已经分配好,可以重复利用 STD库 vector就是该原理)
new(&pa[1]) A();
pa[0].~A(); //只调用析构
pa[1].~A();
free(pa); //释放内存
2.多个类说明
类可以继承其它类(其它类称为父类或者超类). 也可以将其它类用于本类的成员(其它类称为成员类).
类的构造顺序
如果有父类递归构造,从最远的父类开始构造. 构造本类时,按成员在本类的顺序(static 成员除外)依次构造成员.(如果构造函数里顺序不一致会警告,必须在构造函数中保持一致)
析构顺序
如果有父类先析构自己然后析构父类,依次析构(和构造相反). 析构本类时,按成员在本类的反顺序依次析构(和构造相反).
注意:析构时不要调用虚函数!
3.例程
#include <signal.h>
#include "wutility/WUtils.h"
/**构造函数 类第一次实例化时调用 (new一个对象 或者 其它实例对象) 可以有多种构造函数,由输入参数匹配对应的构造函数
* 析构函数 实例消亡时调用 (delete 或者局部变量出了作用域 或者程序结束) 只能由一个析构函数
*/
/**
* new 调用 构造函数
* delete 调用析构函数
* malloc 和free 什么都不调用
*/
class Point //类名
{
public: //公共的 (外部都能调用)
~Point() //析构函数
{
WDBG("~Point");
}
Point() : m_x(0), m_y(0) //默认构造函数
{
WDBG("默认构造 Point");
}
Point(s32 xIn, s32 yIn) : m_x(xIn), m_y(yIn) //有参构造函数 (尽量让输入参数和类的成员名字不同)
{
WDBG("有参数构造 Point");
// x = xIn; 可以再下面复制. 效率没有放:后面高(特别是类)
// y = yIn;
}
s32 x() //get方法 不需要写get (默认本类不能出现x变量!!)
{
return m_x;
}
s32 y()
{
return m_y;
}
void setX(s32 x) //set 方法必须写set
{
m_x = x; // m_x 私有的成员只能通过函数调用
WDBG("Point setX");
}
void setY(s32 y)
{
m_x = y;
WDBG("Point setY");
}
std::string toString() const//格式字符串 类的默认调用方法
{
return WString::formats("[%, %]", m_x, m_y);
}
private: //私有的 (只有本类能调用)
s32 m_x; //类的成员必须以m_ 开头
s32 m_y;
};
class Point2 //和 Point类一样给下面测试用
{
public:
~Point2() //析构函数
{
WDBG("~Point2");
}
Point2() : m_x(0), m_y(0) //默认构造函数(如果没有写该函数,必须传入指定参数才能构造)
{
WDBG("默认构造 Point2");
}
Point2(s32 xIn, s32 yIn) : m_x(xIn), m_y(yIn) //有参构造函数
{
WDBG("有参数构造 Point2");
// x = xIn;
// y =yIn;
}
s32 x()
{
return m_x;
}
s32 y()
{
return m_y;
}
void setX(s32 x)
{
m_x = x;
}
void setY(s32 y)
{
m_x = y;
}
std::string toString() const
{
return WString::formats("[%, %]", m_x, m_y);
}
private:
s32 m_x;
s32 m_y;
};
//使用 Point 类的成员
class PointTh
{
public:
~PointTh() //析构函数
{
WDBG("~PointTh");
}
PointTh() : m_th(0) //默认构造函数
{
WDBG("默认构造 PointTh");
}
//注意构成函数中如果成员函数为有参构造函数需放于 :后面依次构造. 构造顺序为 成员的顺序
//如果类的成员需要使用默认构造函数可以不写
PointTh(s32 xIn, s32 yIn, float thIn) : m_p(xIn, yIn), m_th(thIn)//有参构造函数
{
WDBG("有参数构造 PointTh");
// x = xIn;
// y =yIn;
}
void setTh(s32 th)
{
m_th = th;
}
s32 x()
{
return m_p.x(); //使用成员方法调用 .为方法
}
s32 y()
{
return m_p.y();
}
s32 th()
{
return m_th;
}
std::string toString() //std:: 为命令空间
{
return WString::formats("[%, %,th:%]", m_p.x(), m_p.y(), m_th); //WString :: 为类的静态函数
}
private:
Point m_p; // 有类的成员(可以调用 Point类的public方法)
float m_th; //弧度
};
//继承Point类
// Point的public 方法为本类的方法(如果本类有相同名字则,父类不起作用)
class PointThChild : public Point
{
public:
~PointThChild() //析构函数
{
WDBG("~PointThChild");
}
PointThChild() : Point() //默认构造函数(空的默认构造函数可以不写)
{
WDBG("默认构造 PointThChild");
}
#if 0
PointThChild() //可以不写
{
}
#endif
//注意构成函数中如果父类为有参构造函数,需放:后的第一个位置
//构造顺序 父类先构造,然后为本类的成员!!
//析构的顺序 相反
PointThChild(s32 xIn, s32 yIn, float thIn) : Point(xIn, yIn), m_th(thIn)//有参构造函数
{
WDBG("有参数构造 PointThChild");
}
void setTh(s32 th)
{
m_th = th;
}
void setX(s32 x) //父类的setX不在起作用
{
WDBG("PointThChild setX");
Point::setX(x); //可以显示调用父类的方法
}
std::string toString()
{
return WString::formats("[%, %,th:%]", x(), y(), m_th);
}
private:
float m_th; //弧度
};
//表示 构造和析构的顺序
class Rect
{
public:
Rect(s32 x1, s32 y1, s32 x2, s32 y2) : m_p1(x1, y1), m_p2(x2, y2)
{
}
std::string toString()
{
return WString::formats("[%, %, %, %]", m_p1.x(), m_p1.y(), m_p2.x(), m_p2.y());
}
private:
Point m_p1;
Point2 m_p2;
};
//new的使用
//(只有类中有自己new对象时.需要delete成员. 或者外部移交给本类的new对象)
class RectNew
{
public:
~RectNew()
{
WDBG("~RectNew");
if(m_p1 != WNULL) //由于为new产生必须析构. 防止内存泄露
{
delete m_p1;
m_p1 = WNULL;
WDBG("~RectNew 释放内存");
}
}
RectNew() : m_p1(WNULL)
{ //默认构造函数 指针类型 强制为NULL
WDBG("RectNew 默认构造函数");
}
RectNew(s32 x, s32 y)
{
m_p1 = new Point(x, y);
//有参数的 new 对象 后面为 构造函数填入对应的参数
WDBG("RectNew 有参数构造函数");
}
std::string toString()
{
if(m_p1 == WNULL)
{
return WString::formats("[NULL, NULL]");
}
return WString::formats("[%, %]", m_p1->x(), m_p1->y());
}
private:
Point *m_p1;
};
//不同构造函数出现的场景
class Str
{
public:
// ~Str() //默认析构函数 不写,则自动生成
// {
// }
//
Str()
{
}
Str(const Str& in) : m_st(in.m_st)
{
WDBG("Str 复制构造左值");
}
Str(Str&& in) : m_st(std::move(in.m_st))
{
WDBG("Str 复制构造右值");
}
Str& operator=(const Str &p)
{
WDBG("赋值 左值");
m_st = p.m_st;
return *this;
}
Str& operator=(Str &&p)
{
WDBG("赋值 右值");
m_st = std::move(p.m_st);
return *this;
}
std::string m_st;
};
/*******
c++中创建一个类默认生成的函数
•default构造函数(无参构造函数)
•拷贝构造函数
•=重载操作符函数
•析构函数
•移动构造函数
*/
//默认构造的生成
class Ct
{
public:
s32 m_val;
s32 m_valB;
std::string m_st;
Str m_out;
std::string toString() const
{
return WString::formats("m_val[%],m_valB[%],m_st[%],m_out[%]",
m_val, m_valB, m_st, m_out.m_st);
}
};
//结构体和 class 等同
//区别:结构体 默认为 public class 默认为private
struct St
{ //默认都是public
s32 m_val;
s32 m_valB;
std::string m_st;
Str m_out;
std::string toString() const
{
return WString::formats("m_val[%],m_valB[%],m_st[%],m_out[%]",
m_val, m_valB, m_st, m_out.m_st);
}
};
//extern void tsb();
static void test()
{
// tsb();
{
Point p1;
WDBG("p1=%", p1);
//调用无参数的构造函数
}
WDBG("\r\n");
{
Point p2(3, 4);
WDBG("p2=%", p2);
//调用有参数的构造函数
}
WDBG("\r\n");
{
PointTh p3(4, 5, 2.0);
WDBG("p3=%", p3);
//成员函数 m_p 先构成后为 m_th
//如果成员函数为基本类型 不调用构造函数!!
}
WDBG("\r\n");
{
PointTh p4(4, 5, 2.0);
WDBG("p4=%", p4);
}
WDBG("\r\n");
{
Point p5;
PointTh p6(3, 4, 3.0);
WDBG("p5=%, p6=%", p5, p6);
//构造顺序 为 p5 --> p6
//析构顺序为 p6--> p5
}
WDBG("\r\n");
{
Rect r(1, 2, 3, 4);
WDBG("rect=%", r);
// Rect b; //没写默认构造函数编译失败
//析构顺序为 m_p2--> m_p1
}
{
WDBG("\r\n");
PointThChild p(1, 2, 3);
WDBG("PointThChild p=%", p);
p.setY(10); //调用父类的方法
p.setX(10); //调用子类的方法
WDBG("PointThChild p=%", p);
}
WDBG("\r\n");
{
RectNew rn1;
WDBG("rn1=%", rn1);
}
WDBG("\r\n");
{
RectNew rn2(2, 3);
WDBG("rn1=%", rn2);
}
WDBG("\r\n");
WDBG("\r\n");
WDBG("\r\n");
{ //默认生成的函数和 左值右值
Ct a;
a.m_val = 1;
a.m_valB = 2;
a.m_st = "123";
a.m_out.m_st = "out";
WDBG("Ct a=%", a);
Ct b(a); //默认生成的复制构造函数 左值
WDBG("\r\n");
WDBG("Ct a=%", b);
Ct c;
c = b; //默认生成的赋值函数 左值
WDBG("\r\n");
WDBG("Ct c=%", c);
{
WDBG("\r\n");
Ct d(std::move(c)); //默认生成的复制构造函数 右值
WDBG("Ct d(std::move(c)=%", d);
Ct h;
WDBG("\r\n");
h = std::move(d); //默认生成的赋值函数 右值
WDBG(" Ct h = std::move(d)=%", h);
}
}
WDBG("\r\n");
WDBG("\r\n");
WDBG("\r\n");
{ //默认生成的函数和 左值右值
St a;
a.m_val = 1;
a.m_valB = 2;
a.m_st = "123";
a.m_out.m_st = "out";
WDBG("St a=%", a);
St b(a); //默认生成的复制构造函数 左值
WDBG("\r\n");
WDBG("St a=%", b);
St c;
c = b; //默认生成的赋值函数 左值
WDBG("\r\n");
WDBG("St c=%", c);
{
WDBG("\r\n");
St d(std::move(c)); //默认生成的复制构造函数 右值
WDBG("St d(std::move(c)=%", d);
St h;
WDBG("\r\n");
h = std::move(d); //默认生成的赋值函数 右值
WDBG("St h = std::move(d)=%", h);
}
}
WDBG("\r\n");
}
/**
[DBG] [2021-07-15 15:20:20.813] [main.cpp::main:668] 课程开始
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:18] 默认构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:371] p1=[0, 0]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:376]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:23] 有参数构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:381] p2=[3, 4]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:386]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:23] 有参数构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::PointTh:129] 有参数构造 PointTh
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:391] p3=[4, 5,th:2.000]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~PointTh:118] ~PointTh
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:397]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:23] 有参数构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::PointTh:129] 有参数构造 PointTh
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:402] p4=[4, 5,th:2.000]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~PointTh:118] ~PointTh
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:405]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:18] 默认构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:23] 有参数构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::PointTh:129] 有参数构造 PointTh
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:411] p5=[0, 0], p6=[3, 4,th:3.000]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~PointTh:118] ~PointTh
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:418]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:23] 有参数构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point2:76] 有参数构造 Point2
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:423] rect=[1, 2, 3, 4]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point2:66] ~Point2
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:432]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:23] 有参数构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::PointThChild:192] 有参数构造 PointThChild
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:435] PointThChild p=[1, 2,th:3.000]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::setY:47] Point setY
[DBG] [2021-07-15 15:20:20.815] [main.cpp::setX:202] PointThChild setX
[DBG] [2021-07-15 15:20:20.815] [main.cpp::setX:41] Point setX
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:440] PointThChild p=[10, 2,th:3.000]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~PointThChild:172] ~PointThChild
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:443]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::RectNew:253] RectNew 默认构造函数
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:448] rn1=[NULL, NULL]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~RectNew:241] ~RectNew
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:451]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Point:23] 有参数构造 Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::RectNew:261] RectNew 有参数构造函数
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:457] rn1=[2, 3]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~RectNew:241] ~RectNew
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~Point:13] ~Point
[DBG] [2021-07-15 15:20:20.815] [main.cpp::~RectNew:247] ~RectNew 释放内存
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:461]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:462]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:463]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:473] Ct a=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Str:292] Str 复制构造左值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:477]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:478] Ct a=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::operator=:302] 赋值 左值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:484]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:485] Ct c=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:488]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Str:297] Str 复制构造右值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:491] Ct d(std::move(c)=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:494]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::operator=:310] 赋值 右值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:497] Ct h = std::move(d)=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:501]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:502]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:503]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:513] St a=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Str:292] Str 复制构造左值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:517]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:518] St a=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::operator=:302] 赋值 左值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:524]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:525] St c=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:528]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::Str:297] Str 复制构造右值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:531] St d(std::move(c)=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:534]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::operator=:310] 赋值 右值
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:537] St h = std::move(d)=m_val[1],m_valB[2],m_st[123],m_out[out]
[DBG] [2021-07-15 15:20:20.815] [main.cpp::test:543]
*/
/** 信号退出回调
* @param in signum 信号数
* @return 无
**/
static void closeHandler(int signum)
{
WARG_NO_USE(signum);
int save_errno = errno;
setSysExit();
errno = save_errno;
}
int main(int argc, char **argv)
{
signal(SIGPIPE, SIG_IGN); //忽略网络异常
signal(SIGINT, closeHandler);
signal(SIGTERM, closeHandler);
WDBG("课程开始");
test();
}