0623第七讲拷贝构造函数
拷贝构造函数:
1、定义:通过一个已经存在的对象来创建新对象(构造函数参数是一个对象)Circle(const Circle &c);
2、拷贝构造函数调用情况
1)用一个对象初始化另一个对象
Classname object(otherObject);//拷贝构造函数
Classname object = otherObject;//拷贝构造函数
Classname object;
object = otherObject;//赋值运算符
2)函数以值传递的形式,实參赋值给形參,调用拷贝构造函数
void func(Person p);
func(object);
3)函数值返回形式返回一个对象,返回值会调用拷贝构造函数创建一个临时变量用来使用。
Person func(){
Person p;
return p;
}回去用vc测试一下
3、拷贝构造函数编写:
1)开辟新空间
2)赋值
Class(const &obj);
注意:拷贝构造函数参数必须是一个引用
如果拷贝构造函数的参数是以值传递的话,他本身执行时也需要穿參,而穿參时又要调用拷贝构造函数,2.1->2.2->2.1->……程序进入死循环。如果是传引用的方式的话就不会出现这个情况。
Person(Person& p)//ok
Person(Person p)//error
{…}
Person p1(p2);
如果成员变量包含指针,程序猿必须实现3个函数(拷贝构造函数、析构函数、赋值运算符重载函数)
构造函数和类型转换:当构造函数只有一个参数,可以自动将形參转换成对象
拷贝与构造:
Demo foo(Demo x){
Demo d;//4.构造函数被调用
return d;
}
int main(int argc, const char * argv[]) {
Demo a(2);//1.构造函数被调用
{
Demo b;//2.构造函数被调用
b=foo(a);//3.拷贝构造函数被调用
//5.赋值运算符函数被调用
}//6.析构函数被调用//7.析构函数被调用//8.析构函数被调用 析构x,d,b
Demo c=a;//9.拷贝构造函数被调用
//10.析构函数被调用//11.析构函数被调用 析构c,a
return 0;
}
Person.hpp
#ifndef person_hpp
#define person_hpp
#include <stdio.h>
#include <iostream>
using namespace std;
class Person
{
friend ostream& operator<<(ostream& out,const Person& p);
private:
char *name;
char sex[6];
int age;
char hobby[20];
public:
Person(char* name);
Person(const Person& p);
~Person();
Person();
Person(char *_name,char *_sex,int _age,char *_hobby);
void setPerson(char *_name,char *_sex,int _age,char *_hobby);
char* getName()const;
void print();
void setName(char *name);
Person& operator=(Person& p);
};
#endif
Person.cpp
#include "person.hpp"
#include "iostream"
#include "string"
using namespace std;
char* Person:: getName()const
{
return name;
}
Person::Person(char* _name)
{
this->name=new char[strlen(_name)+1];
strcpy(name, _name);
cout<<"调用单个参数构造函数"<<endl;
}
Person::Person(const Person& p)
{
this->name=new char[strlen(p.name)+1];
strcpy(name, p.name);
strcpy(sex, p.sex);
age=p.age;
strcpy(hobby, p.hobby);
cout<<"调用拷贝构造函数"<<endl;
}
ostream& operator<<(ostream& out,const Person& p)
{
out<<"姓名:\t" <<p.name<<"\t性别:\t"<<p.sex<<"\t年龄:\t"<<p.age<<"\t爱好:\t"<<p.hobby<<endl;
return out;
}
Person& Person:: operator=(Person& p)
{
if (this != &p) {
delete [] this->name;
this->name=NULL;
name=new char [strlen(p.name)+1];
strcpy(this->name ,p.name);
strcpy(this->sex ,p.sex);
this->age=p.age;
strcpy(this->hobby ,p.hobby);
}
cout<<"调用重载的赋值运算符"<<endl;
return *this;
}
Person::~Person()
{
if (name!=NULL) {
delete []name;
name=NULL;
}
cout<<"调用Person析构函数"<<endl;
}
Person::Person()
{
name=NULL;
// strcpy(name, "");
// strcpy(sex, "");
age=0;
// strcpy(hobby, "");
cout<<"调用Person默认构造函数"<<endl;
}
Person::Person(char *_name,char *_sex,int _age,char *_hobby)
{
name=new char[strlen(_name)+1];
strcpy(name, _name);
strcpy(sex, _sex);
age=_age;
strcpy(hobby, _hobby);
cout<<"调用Person有參构造函数"<<endl;
}
void Person::setPerson(char *_name,char *_sex,int _age,char *_hobby)
{
strcpy(name, _name);
strcpy(sex, _sex);
age=_age;
strcpy(hobby, _hobby);
}
void Person::print()
{
cout<<"姓名:\t" <<name<<"\t性别:\t"<<sex<<"\t年龄:\t"<<age<<"\t爱好:\t"<<hobby<<endl;
}
void Person::setName(char *name)
{
strcpy(this->name, name);
cout<<"设置name"<<endl;
}
main.cpp
#include <iostream>
using namespace std;
#include "person.hpp"
void print(const Person& p)
{
cout<<"name = "<<p.getName()<<endl;
}
int main(int argc, const char * argv[]) {
Person p1((char*)"jiji");//默认构造函数,把字符串转成临时对象
print(p1);
print((char*)"lily");//调用单个参数构造函数构造临时对象,函数结束释放
Person p2=(char*)"lilei";
print(p2);
Person array[]={(char*)"caoqiang",(char*)"heyi",(char*)"yangyang",(char*)"zhangke",(char*)"peizhengmeng",(char*)"baoming"};
for (int i=0; i<6; ++i) {
print(array[i]);
}
return 0;
}
课堂练习
写一个Student类
属性:char *name ,int score ,char *label,int grade,char enjoy[20]
行为:默认构造函数、有參数的构造函数、拷贝构造函数、析构函数、输出运算符重载、赋值运算符重载
CStudent.hpp
#ifndef CStudent_hpp
#define CStudent_hpp
#include <stdio.h>
#include <iostream>
using namespace std;
class CStudent
{
friend ostream& operator<<(ostream& out,const CStudent& s);
private:
char* name;
int score;
char* label;
int grade;
char enjoy[20];
public:
// CStudent();
CStudent(char* _name=(char*)"",int _score = 0,char* _label=(char*)"",int _grade = 0,char* enjoy=(char*)"");
CStudent(CStudent& s);
~CStudent();
void operator=(CStudent& s);
};
#endif
CStudent.cpp
#include "CStudent.hpp"
#include <string>
using namespace std;
ostream& operator<<(ostream& out,const CStudent& s)
{
out<<"调用重载输出运算符函数"<<endl;
out<<"name = "<<s.name<<endl;
out<<"score = "<<s.score<<endl;
out<<"label = "<<s.label<<endl;
out<<"grade = "<<s.grade<<endl;
out<<"enjoy = "<<s.enjoy<<endl;
return out;
}
//CStudent::CStudent(){
//
//}
CStudent::CStudent (char* _name,int _score,char* _label,int _grade,char* _enjoy):score(_score),grade(_grade){
name=new char[strlen(_name)+1];
strcpy(name, _name);
label=new char[strlen(_label)+1];
strcpy(label, _label);
strcpy(enjoy, _enjoy);
cout<<"调用构造函数"<<endl;
}
CStudent::CStudent(CStudent& s){
name=new char[strlen(s.name)+1];
strcpy(name, s.name);
label=new char[strlen(s.label)+1];
strcpy(label, s.label);
strcpy(enjoy, s.enjoy);
score=s.score;
grade=s.grade;
cout<<"调用拷贝构造函数"<<endl;
}
CStudent::~CStudent(){
if (name != NULL) {
delete []name;
name = NULL;
}
if (label != NULL) {
delete []label;
label = NULL;
}
cout<<"调用析构函数"<<endl;
}
void CStudent::operator=(CStudent& s){
cout<<"调用重载赋值运算符函数"<<endl;
if (this!=&s) {
delete []name;
name=NULL;
delete []label;
label=NULL;
name = new char [strlen(s.name)+1];
strcpy(name, s.name);
label = new char [strlen(s.label)+1];
strcpy(label, s.label);
strcpy(enjoy, s.enjoy);
score=s.score;
grade=s.grade;
}
}
main.cpp
#include <iostream>
#include "CStudent.hpp"
using namespace std;
CStudent func(CStudent _s)
{
CStudent s=_s;
return s;
}
int main(int argc, const char * argv[]) {
CStudent s1((char*)"lily",100, (char*)"n",1, (char*)"study");
CStudent s2(s1);
// cout<<"s1\n"<<s1<<"------------\n"<<"s2\n"<<s2<<endl;
CStudent s3=s1;
// cout<<"s1\n"<<s1<<"s3\n"<<s3<<endl;
CStudent s4;
s4=s3;
func(s4);
cout<<"s3\n"<<s3<<"s4\n"<<s4<<endl;
}
输出结果:
调用构造函数
调用拷贝构造函数
调用拷贝构造函数
调用构造函数
调用重载赋值运算符函数
调用拷贝构造函数
调用拷贝构造函数
调用析构函数
调用析构函数
s3
调用重载输出运算符函数
name = lily
score = 100
label = n
grade = 1
enjoy = study
s4
调用重载输出运算符函数
name = lily
score = 100
label = n
grade = 1
enjoy = study
调用析构函数
调用析构函数
调用析构函数
调用析构函数
Program ended with exit code: 0