概述
构造函数
在创建C++对象实例化后,其内部数据是随机值,对于C而言,通常采用初始化函数进行初始化,而在C++中,可以认为初始化工作交给了构造函数完成。
关于构造函数必须要了解的有:
-
构造函数的函数名必须和class类名一样,可以带形参也可以不带,但不能有返回值,如同人一生只能出生一次,对于一个实例而言,一生只能构造一次 。
-
构造函数可以重载 ,即构造函数的参数可以不一样 。创建对象时根据传递的实参来判断调用哪一个构造函数。但是如果构造函数参数中有默认值,那么将无法确定哪个函数作为初始化,不能重载。
-
构造函数不需要用户显式调用(用户也不能调用),而是在创建对象时自动执行。
-
允许使用一个对象初始化另一个对象,这种方式称为拷贝构造方法。
test t3(t1);
(详见代码)。值得注意的是,拷贝方法在创建对象时并不会调用构造函数。
默认构造函数
如果用户自己没有定义构造函数,那么编译器会自动生成一个默认的构造函数,只是这个构造函数的函数体是空的,也没有形参,也不执行任何操作。但用户一旦定义,则系统不在默认构造函数,因此,在实例化对象时要注意。默认生成的构造函数如下:
test(){}
析构函数
创建对象后需要对对象做“销毁”,C++中析构函数担当了这一角色。与构造函数相比,析构函数的函数名必须是”~类名“(~test()
)的形式。析构函数没有返回值,不能显式调用,而是在销毁对象时自动执行。同构造函数类似,如果用户没有定义,编译器会自动生成一个默认的析构函数。
析构函数的执行时机
析构函数在对象被销毁时调用,而对象的销毁时机与它所在的内存区域有关。
在所有函数之外创建的对象是全局对象,它和全局变量类似,位于内存分区中的全局数据区,程序在结束执行时会调用这些对象的析构函数。
在函数内部创建的对象是局部对象,它和局部变量类似,位于栈区,函数执行结束时会调用这些对象的析构函数。
new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。
#include <iostream>
#include <string>
using namespace std;
class Demo{
public:
Demo(string s);
~Demo();
private:
string m_s;
};
Demo::Demo(string s): m_s(s){ }
Demo::~Demo(){ cout<<m_s<<endl; }
void func(){
//局部对象
Demo obj1("1");
}
//全局对象
Demo obj2("2");
int main(){
//局部对象
Demo obj3("3");
//new创建的对象
Demo *pobj4 = new Demo("4");
func();
cout<<"main"<<endl;
return 0;
}
//运行结果:
//1
//main
//3
//2
this指针
this指针是 C++ 中的一个关键字,也是一个默认存在的 const 指针,它指向当前对象。this 只能用在类的内部,通过 this 可以访问类的所有成员,包括 private、protected、public 属性的。
几点注意:
this 是 const 指针,它的值是不能被修改的,一切企图修改该指针的操作,如赋值、递增、递减等都是不允许的。 this
只能在成员函数内部使用,用在其他地方没有意义,也是非法的。 只有当对象被创建后 this 才有意义,因此不能在 static
成员函数中使用(后续会讲到 static 成员)。
this 实际上是成员函数的一个形参,在调用成员函数时将对象的地址作为实参传递给 this。不过 this 这个形参是隐式的,它并不出现在代码中,而是在编译阶段由编译器默默地将它添加到参数列表中。
this 作为隐式形参,本质上是成员函数的局部变量,所以只能用在成员函数的内部,并且只有在通过对象调用成员函数时才给 this 赋值。
在*《C++函数编译原理和成员函数的实现》*一节中讲到
成员函数最终被编译成与对象无关的普通函数,除了成员变量,会丢失所有信息,所以编译时要在成员函数中添加一个额外的参数,把当前对象的首地址传入,以此来关联成员函数和成员变量。这个额外的参数,实际上就是this,它是成员函数和成员变量关联的桥梁。
int count=1;
class test{
public:
int pu_a;
test(int data){//构造函数1
a=data;
pu_a=data;
cout<<"t1 this的地址:" <<this<<endl;
}
test(){
cout<<"t2 this的地址:" <<this<<endl;
}
//析构函数<收尸 >,释放对象而非空间
~test()
cout<<"this指针位置:"<<this<<' '<<count++<<endl;
}
//拷贝构造方法(使用对象初始化对象);在对象作为函数的值传递时常用到
//void fun(test t1) ;
//test fun(test t2);(构造无名临时对象返回,即返回时也会调用拷贝方法)
test(const test & t){//函数名与类相同,注意参数 ,语法要求引用传递 ,不然会递归下去
a=t.a;
cout<<"拷贝构造this地址"<<this<<endl;
}
private:
int a;
};
test fun(test t){
cout<<"函数_拷贝构造函数调用"<<endl;
}
int main(){
test t1(1),t2; //两者的构造函数不同
test t3(t1);//等价于test t3=t1。使用t1构造t3,不会调用构造函数 ,而是拷贝构造方法,但会调用析构函数
test t4(t3);
cout<<"初始化值: "<<t1.pu_a<<endl;
cout<<"===程序==="<<endl;
//t1 this的地址:0x6bfee8
//t2 this的地址:0x6bfee0
//拷贝构造this地址0x6bfed8
//this指针位置:0x6bfed8 1
//this指针位置:0x6bfee0 2
//this指针位置:0x6bfee8 3
//注意地址,在栈上
fun(t1);
//t1 this的地址:0x6bfed8
//t2 this的地址:0x6bfed0
//拷贝构造this地址0x6bfec8
//拷贝构造this地址0x6bfec0
//初始化值: 1
//===程序===
//拷贝构造this地址0x6bfee8
//函数_拷贝构造函数调用
//this指针位置:0x6bfee0 1
//this指针位置:0x6bfee8 2
//this指针位置:0x6bfec0 3
//this指针位置:0x6bfec8 4
//this指针位置:0x6bfed0 5
//this指针位置:0x6bfed8 6
其中test fun(test t)会调用两次拷贝,一次传值,一次返回
return 0;
}
}
最后
以上就是烂漫背包为你收集整理的构造函数和析构函数的全部内容,希望文章能够帮你解决构造函数和析构函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复