类的构造函数
就是初始化函数,在创建对象时,为每个对象初始化数据成员
#include <iostream>
using namespace std;
class line
{
public:
line(int len); //
int getline();
void setline(int l);
private:
int length;
};
line::line(int len) {
length = len;
}
void line::setline(int l) {
length = l;
}
int line::getline() {
return length;
}
int main() {
line myline(18);
cout << myline.getline() << endl;
myline.setline(19);
cout << myline.getline() << endl;
return 0;
}
class line
{
public:
line(int len); //
int getline();
void setline(int l);
private:
int length;
};
其中的line(int len);
就是构造函数的声明;
这是定义:
line::line(int len) {
length = len;
}
定义也可以这么写:
line::line(int len): length(len) {}
参数多的话就用逗号分开:
line::line(int len, int w): length(len), weight(w) {}
当然,也可以直接在类里面写定义:
class line
{
public:
line(int len, int w): length(len), weight(w) {};
int getline();
int getweight();
void setline(int l);
private:
int length;
int weight;
};
注意,结构体也可以这么写:
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :
val(x), left(NULL), right(NULL), next(NULL) {
}
};
类的析构函数
类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。
析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
不需要显式调用,程序结束后,自动调用
#include <iostream>
using namespace std;
class line
{
public:
line(int len, int w): length(len), weight(w) {};
int getline();
int getweight();
void setline(int l);
~line(){cout << "hhh" << endl;};
private:
int length;
int weight;
};
void line::setline(int l) {
length = l;
}
int line::getline() {
return length;
}
int line::getweight() {
return weight;
}
int main() {
line myline(18, 50);
cout << myline.getline() << endl;
cout << myline.getweight() << endl;
myline.setline(19);
cout << myline.getline() << endl;
return 0;
}
18
50
19
hhh
拷贝构造函数
什么情况使用拷贝构造函数:
类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体
(2)一个对象以值传递的方式从函数返回
(3)一个对象需要通过另外一个对象进行初始化。
为什么用拷贝构造函数
当出现类的等号赋值时,会调用拷贝函数,在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。
当数据成员中没有指针时,浅拷贝是可行的。但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。所以,在某些情况下,浅拷贝回带来数据安全方面的隐患。
当类的数据成员中有指针类型时,我们就必须定义一个特定的拷贝构造函数,该拷贝构造函数不仅可以实现原对象和新对象之间数据成员的拷贝,而且可以为新的对象分配单独的内存资源,这就是深拷贝构造函数。
所以,这时,必须采用深拷贝。
深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝。
#include <iostream>
using namespace std;
class Line
{
public:
int getLength( void );
Line( int len ); // 简单的构造函数
Line( const Line &obj); // 拷贝构造函数
~Line(); // 析构函数
private:
int *ptr;
};
// 成员函数定义,包括构造函数
Line::Line(int len)
{
cout << "调用构造函数" << endl;
// 为指针分配内存
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj)
{
cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
ptr = new int;
*ptr = *obj.ptr; // 拷贝值
}
Line::~Line(void)
{
cout << "释放内存" << endl;
delete ptr;
}
int Line::getLength( void )
{
return *ptr;
}
void display(Line obj)
{
cout << "line 大小 : " << obj.getLength() <<endl;
}
// 程序的主函数
int main( )
{
Line line1(10);
Line line2 = line1; // 这里也调用了拷贝构造函数
display(line1);
display(line2);
return 0;
}
函数声明:
Line( const Line &obj);
函数定义:
Line::Line(const Line &obj)
{
cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
ptr = new int;
*ptr = *obj.ptr; // 拷贝值
}
调用构造函数
调用拷贝构造函数并为指针 ptr 分配内存
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
调用拷贝构造函数并为指针 ptr 分配内存
line 大小 : 10
释放内存
释放内存
释放内存