C++构造函数与析构函数

构造函数是特殊的成员函数
全局对象的构造优于main函数
Test.h:
#ifndef _TEST_H
#define _TEST_H

class Test
{
	//如果类不提供任何一个构造函数,系统将为我门提供一个默认构造函数
        //当类中有一个构造函数,系统不必提供默认构造函数
public:
	Test();
	Test(int num_);
	void Display();
private:
	int num;
public:
    ~Test();
    //析构函数不能重载
};

   
   
Test.cpp:
#include "Test.h"
#include <iostream>
using namespace std;
//不带参数的构造函数称为默认构造函数
Test::Test()
{
num = 0;
cout << "Initializing Default" << endl;
}
void Test::Display()
{
cout << num << endl;
}
Test::Test(int num_)
{
num = num_;
cout << num << endl;
}
Test::~Test()
{
cout << "Destory" << num << endl;
}
02.cpp:
#include "Test.h"
#include <iostream>
using namespace std;
//全局对象的构造要优于main函数的构造
//Test t(10);
/*
int main()
{
cout << "Entering main ...." << endl;
cout << "exiting main" << endl;
return 0;
}
*/
栈中创建的对象,在生存期结束时会自动调用析构函数
堆上创建的对象,必须要程序员显示调用delete释放该对象
#include "Test.h"

/*
int main()
{
    Test t[2] = {10 , 20};

    Test *t2 = new Test(2);
    delete t2;

    Test* t3 = new Test[2];//调用默认构造函数
    delete[] t3;//删除数组必须要使用的delete[]
    return 0;
}
*/

   
   
#include "Test.h"
int main()
{
Test t;
// t.Test(3);
t.~Test(); //析构函数可以被显示调用,构造函数不可以
return 0;
}

转换构造函数

单个参数的构造函数
类型转换(将其他类型转换为类类型)
只有一个参数的构造函数是危险的:因为编译器可以使用这种构造函数把参数的类型隐式转换为类类型。
Test.h:
#ifndef _TEST_H
#define _TEST_H

class Test
{
	//如果类不提供任何一个构造函数,系统将为我门提供一个默认构造函数
       //当类中有一个构造函数,系统不必提供默认构造函数
public:
	Test();
	explicit Test(int num_);
	void Display();	
	Test& operator=(const Test& other);	
private:
	int num;
public:
    ~Test();
    //析构函数不能重载
};

#endif


   
   
Test.cpp:
#include "Test.h"
#include <iostream>
using namespace std;
//不带参数的构造函数称为默认构造函数
Test::Test()
{
num = 0;
cout << "Initializing Default" << endl;
}
void Test::Display()
{
cout << num << endl;
}
Test::Test(int num_)
{
num = num_;
cout << num << endl;
}
Test::~Test()
{
cout << "Destory" << num << endl;
}
Test& Test::operator=(const Test& other)
{
num = other.num;
cout << "运算符" << endl;
return *this;
}
#include "Test.h"
int main()
{
//Test t;
Test t(10); //此时并不是转换构造函数,只是普通构造函数功能
t = 20;//要将20 这个整数赋值给t对象
//1、调用装换构造函数将20这个整数转换为类类型(生成一个临时对象)
//2、静临时对象赋值给t对象(调用=运算符)
//Test t2;
return 0;
}
赋值与初始化的区别:
例如:
#include "Test.h"

int main()
{
Test t = 10;
//初始化语句中=不是赋值运算符而是等价于Test t(10)
t = 20;//赋值操作
Test t2;
t = t2;//赋值操作
return 0;
}
explicit

只提供给类的构造函数使用的关键字
编译器不会把声明explicit的构造函数用于隐式转换,他只能在程序代码中显示创建对象。

构造函数初始化列表


推荐在构造函数初始化列表进行数据初始化
构造函数执行的两个阶段
数据成员初始化
普通计算

对象成员及其初始化
const成员、引用成员初始化
const成员的初始化只能在构造函数的初始化列表中初始化
引用成员的初始化只能在构造函数的初始化列表中初始化
对象成员(如无默认构造函数)的初始化只能在构造函数的初始化列表中初始化

Clock.h:
#ifndef _CLOCK_H_
#define _CLOCK_H_
class Clock
{
public:
    Clock(int hour = 0, int minute = 0 , int second = 0);
	~Clock();
public:
    void Display();
    void Update();
    void Init(int hour , int minute , int second);
public:
    int hour_,minute_,second_;
};
#endif // _CLOCK_H_
--------------------------------------------------------------------------------
Clock.cpp:
#include "Clock.h"
#include <iostream>
using namespace std;


Clock::Clock(int hour , int minute , int second ) : hour_(hour),minute_(minute),second_(second)
{
	/*
	hour_ = hour;
    minute_ = minute;
    second_ = second;
*/
	}

Clock::~Clock()
{
	cout << "Clock::~Clock" << endl;
}

void Clock::Display(){
    cout << hour_ << ":" << minute_ << ":" << second_ << endl;
}

void Clock::Init(int hour , int minute , int second)
{
    hour_ = hour;
    minute_ = minute;
    second_ = second;
}

void Clock::Update()
{

    if(second_ == 60){
        minute_ ++;
        second_ = 0;
    }
    if(minute_ == 60){
        hour_ ++;
        minute_ = 0;
    }
    if(hour_ == 24){
        hour_ = 0;
    }
}
--------------------------------------------------------------------------------
02.cpp:
#include <iostream>
using namespace std;

class Object
{
	public:
	Object(int num_):num(num_)
	{
		cout << "Object"  << num << endl;
	}
	
	Object()
	{
		cout << "Object" << endl;
	}
	~Object()
	{
		cout << "~Object"  << num << endl;
	}
	private:
	int num;
};

class Container
{
	public:
	Container(int obj1 = 0  , int obj2 = 0 ) : obj2(obj2),obj(obj1)
	//初始化顺序与初始化列表参数顺序无关,而与成员顺序有关
	{
		cout << "Container" << endl;
	}
	~Container()
	{
		cout << "~Container" << endl;
	}
	private:
	Object obj;
	Object obj2;
};
int main()
{
	Container c(10 , 20);
	return 0;
}
枚举常量对于任何对象都是确定的值
enum E_TYPE
{
TYPE_A = 100,
TYPE_B = 200
};
例如:
#include <iostream>
using namespace std;

class Object
{
public:
//枚举常量对于任何对象都是确定的值
enum E_TYPE
{
TYPE_A = 100,
TYPE_B = 200
};
public:
Object(int num_ = 0):num(num_),kNum(50),zefNum(num_)
//const 成员的初始化只能在构造函数的初始化列表中初始化
//引用成员的初始化只能在构造函数的初始化列表中初始化
//对象成员(如无默认构造函数)的初始化只能在构造函数的初始化列表中初始化
{
//kNum = 100;
cout << "Object" << num << endl;
}
~Object()
{
cout << "~Object" << num << endl;
}
void Display()
{
cout << kNum << endl;
}
private:
int num;
const int kNum ;
int& zefNum;
};

int main()
{
Object obj1(10);
Object obj2(20);
obj1.Display();
obj2.Display();
cout << Object::TYPE_A << endl;
cout << obj1.TYPE_A << endl;
cout << obj2.TYPE_A << endl;
return 0;
}
拷贝构造函数:使用一个为已经存在的对象初始化一个新的同一类型的对象。
声明:只有一个参数并且参数为该类对象的引用。
如果类中没有说明拷贝构造函数,则系统自动生成一个缺省复制构造函数,作为该类的共有成员。

例如:
test.h:
#ifndef _TEST_H
#define _TEST_H

class Test
{
//如果类不提供任何一个构造函数,系统将为我门提供一个默认构造函数
//当类中有一个构造函数,系统不必提供默认构造函数
public:
Test();
Test(const Test& t);
explicit Test(int num_);
void Display();
Test& operator=(const Test& other);
private:
int num;
public:
~Test();
//析构函数不能重载
};

#endif

test.cpp:
#include "Test.h"
#include <iostream>

using namespace std;

//不带参数的构造函数称为默认构造函数
Test::Test():num(0)
{
//num = 0;
cout << "Initializing Default" << endl;
}

Test::Test(const Test& t):num(t.num)
{
//参数必须是Const Test&,如果那么做则会产生递归产生对象
cout << "拷贝构造函数" << num << endl;
}

void Test::Display()
{
cout << num << endl;
}

Test::Test(int num_)
{
num = num_;
cout << "初始化" << num << endl;
}

Test::~Test()
{
cout << "Destory" << num << endl;
}

Test& Test::operator=(const Test& other)
{
num = other.num;
cout << "运算符" << endl;
return *this;
}

01.cpp:
#include "Test.h"

int main()
{
Test t(20);
//Test t2(t); //调用拷贝构造函数
//如果类中没有说明拷贝构造函数,则系统自动生成一个缺省复制构造函数,作为该类的共有成员
Test t2 = t;
return 0;
}

拷贝构造函数调用的几种情况
当函数的形参是类的对象,调用函数时,进行形参与实参结合时使用。这时要在内存新建立一个局部对象,并把实参拷贝到新的对象中。理所当然也调用拷贝构造函数。
当函数的返回值是类对象,函数执行完成返回调用者时使用。理由也是要建立一个临时对象中,再返回调用者。为什么不直接用要返回的局部对象呢?因为局部对象在离开建立它的函数时就消亡了,不可能在返回调用函数后继续生存,所以在处理这种情况时,编译系统会在调用函数的表达式中创建一个无名临时对象,该临时对象的生存周期只在函数调用处的表达式中。所谓return 对象,实际上是调用拷贝构造函数把该对象的值拷入临时对象。如果返回的是变量,处理过程类似,只是不调用构造函数。

例如:
02.cpp:
#include "Test.h"

void TestFun(const Test other)
{
}

void TestFun2(const Test& other)
{
//建议引用,可以减少内存创建
}

Test TestFun3(const Test& other)
{
return other ;
}

const Test& TestFun4(const Test& other)
{
return other ;
}

int main()
{
int a = 3;
int& b = a;
Test t(20);
//TestFun(t);
//TestFun2(t);
//TestFun3(t);
Test t2 = TestFun3(t);
Test& t3 = TestFun3(t);
Test t4 = TestFun4(t);
const Test& t5 = TestFun4(t);
return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值