CPP_类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

时间:2022-05-26 08:53:43

类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

// person.h
#ifndef _PERSON_H_
#define _PERSON_H_ class Person{
public :
Person();
Person(int myage, char *myname);
Person(const Person &a);
Person& operator=(const Person& other);
~Person(void); void set_age(int myage);
int get_age(void) const;
void set_other_age(Person &a, int b);
void print() const; private:
int age;
char *name;
}; #endif
// person.cc
#include "person.h" #include <iostream>
#include <stdio.h>
#include <string.h> using namespace std; Person::Person():age(), name(NULL)
{
//nothing
cout<<"no param construct!"<<endl;
} Person::Person(int myage, char *myname)
{
age = myage;
if(myname != NULL){
name = new char[strlen(myname) + ];
this->print();
strcpy(name, myname);
}
cout<<"param construct!"<<endl;
} Person::Person(const Person &a)
{
cout <<"copy constructor!"<<endl;
if(a.name != NULL){
name = new char[strlen(a.name)+];
this->print();
strcpy(name, a.name);
age = a.age;
} else {
name = NULL;
age = ;
}
}
Person& Person::operator=(const Person &a)
{
cout <<"= constructor!"<<endl;
if(&a == this){
return *this;
} if(name != NULL){
delete [] name;
name = NULL;
}
if(a.name != NULL){
name = new char[strlen(a.name)+];
this->print();
strcpy(name, a.name);
age = a.age;
} else {
name = NULL;
age = ;
} return *this;
} Person::~Person()
{
if(NULL != name){
delete [] name;
name = NULL;
}
cout<<"destructor!"<<endl;
}
void Person::set_age(int myage)
{
age = myage;
} int Person::get_age(void) const
{
return age;
} void Person::set_other_age(Person& a, int b)
{
a.age = b;
//a.set_age(b);
} void Person::print() const
{
if(name != NULL)
cout <<"value:" << name;
cout<< " name=" << static_cast<void*> (name) << endl;
}
// main.cc
#include "person.h" #include <iostream>
using namespace std; int main(int argc, char *argv[])
{
Person a(, "xiaohhhhh");
Person b(, "mingttttt");
Person m; m = b;
a.print();
b.print();
m.print(); Person n(, "qing");
b=n;
a=n;
m=n;
a.print();
b.print();
m.print(); return ;
}

构造函数、析构函数和赋值函数是类最重要的函数,被称为The Big Three。
与其他成员函数相比,The big three特殊之处在于,如果代码中没有提供这些函数的实现,C++编译器自动合成缺省的函数实现。
有指针成员变量的类一定要提供The Big Three的实现,即使没有指针变量,作为良好的编程习惯也应该提供The Big Three的实现。

1. 构造函数

和类同名,无返回值,用来初始化类的对象。
构造函数可重载。
编译器提供默认无参构造函数,若声明新的,则采用新的构造函数。一般多应创建一个无参的构造函数,因为创建了有参构造函数后,默认的无参构造函数被覆盖。
构造函数在对象创建后马上调用。
Person a; //调用无参构造函数
Person a(20, "Xiaoming"); //调用两参构造函数
Person(int age=0, const char *name = NULL);构造函数,相当于创建无参或两参构造函数。

2.拷贝构造函数

Person(const Person &a);
如果没有提供拷贝构造函数,编译器会默认提供一个(执行逐个成员初始化,将新对象初始化为原对象的副本,这里的逐个是指编译器将现有对象的每个非static成员,依次复制到正在创建的对象)。
如果类有指针成员变量或类数据成员管理资源(如打开一个文件),默认构造函数并不会自动分配指针所指向的空间(默认构造函数仅提供浅拷贝),需要添加拷贝构造函数实现深拷贝。
默认拷贝构造函数实现浅拷贝:指针成员变量指向同一存储区域,而不是重新分配区域再赋值(深拷贝)。
如果想禁止一个类的拷贝构造,需要将拷贝构造函数声明为private。

3. 析构函数

析构函数不可重载。
类名前加~的函数,无参数,无返回值。
先调用析构函数->后销毁对象。
默认的析构函数不会释放指针成员变量分配的内存区域,可能造成内存泄露。有指针成员变量时必须实现析构函数。

4. 赋值函数

Person& operator=(const Person& other);
基本与拷贝构造等价。如果想禁止一个类的赋值函数,需要将拷贝构造函数声明为private。
Person b=a; //拷贝构造函数
Person b;
b = a; //赋值函数 operator=

5. 构造函数的初始化列表

const变量必须用初始化列表进行初始化。
Person():age(10), name(NULL)中":age(10),name(NULL)"为初始化列表。

6. set_other_age()同一类的不同对象可以访问其他对象的私有数据。

7. this指针

每个成员方法都包含一个隐藏参数this,this是一个对象的指针,指向调用函数的对象。
判断自赋值:

if(this == &a){
return *this;
}