1 C++类的普遍写法
新建NBAPlayer.cpp文件
#include "NBAPlayer.h"
void NBAPlayer::setAge(int age){
this->age = age;
}
int NBAPlayer::getAge(){
return this->age;
}
void NBAPlayer::setName(char *name){
this->name = name;
}
char* NBAPlayer::getName(){
return this->name;
}
新建NBAPlayer.h文件
#pragma once
class NBAPlayer{
public:
int age;
char *name;
public:
void setAge(int age);
int getAge();
void setName(char *name);
char *getName();
};
调用
#include "NBAPlayer.h"
void main(){
NBAPlayer n1;
n1.name = "WestBrook";
n1.age = 28;
cout << n1.getName() <<endl;
system("pause");
}
打印结果
WestBrook
2 构造函数
对象初始化时调用
class NBAPlayer{
private:
char *name;
int age;
public:
//无参构造函数(会覆盖默认的午餐构造函数)
NBAPlayer(){
cout << "无参构造函数" << endl;
}
//有参构造函数会覆盖默认的构造函数
NBAPlayer(char *name,int age){
this->name = name;
this->age = age;
cout << "有参构造函数"<<endl;
}
};
void main(){
NBAPlayer n;
system("pause");
}
打印结果
无参构造函数
当调用有参数构造时:
void main(){
NBAPlayer n2("Durrant",28);
system("pause");
}
打印结果
有参构造函数
另外一种调用方式
NBAPlayer n3 = NBAPlayer("Stephen Curry",29);
3 拷贝构造函数
对象销毁时调用
class NBAPlayer{
private:
char *name;
int age;
public:
NBAPlayer(){
this -> name = (char*)malloc(100);
strcpy(name,"Rose");
age = 30;
cout << "无参构造函数" << endl;
}
//析构函数
//当对象要被系统释放时,析构函数被调用
~NBAPlayer(){
cout << "析构" << endl;
//释放内存
free(this->name);
}
};
void func(){
NBAPlayer n;
}
void main(){
func();
system("pause");
}
打印结果
无参构造函数
析构
4 拷贝构造函数
class NBAPlayer{
private:
char *name;
int age;
public:
NBAPlayer(char*name,int age){
this->name = name;
this->age = age;
cout << "有参构造函数" << endl;
}
//拷贝函数
//默认拷贝构造函数,是值拷贝
NBAPlayer(const NBAPlayer &obj){
this->name=obj.name;
this->age = obj.age;
cout << "拷贝构造函数" << endl;
}
void myPrint(){
cout << name << "," << age << endl;
}
};
1 声明时赋值
void main(){
NBAPlayer n("Derric Rose",29);
//拷贝构造函数被调用的场景
//1 声明时赋值
NBAPlayer n1 = n;
n1.myPrint();
system("pause");
}
打印结果
有参构造函数
拷贝构造函数
Derric Rose,29
2 作为参数传入方法
void func(NBAPlayer n){
n.myPrint();
}
void main(){
NBAPlayer n("Derric Rose",29);
//2 作为参数传入 实参给形参赋值
func(n);
system("pause");
}
打印结果
有参构造函数
拷贝构造函数
Derric Rose,29
3 作为参数返回值返回,给变量初始化赋值
NBAPlayer func1(NBAPlayer n){
n.myPrint();
return n;
}
void main(){
NBAPlayer n("Derric Rose",29);
//3 作为参数返回值返回,给变量初始化赋值
NBAPlayer n2 = func1(n);
system("pause");
}
打印结果
有参构造函数
拷贝构造函数
Derric Rose,29
拷贝构造函数
可以看出最后一个拷贝函数执行是返回值给变量赋值时调用的。
总而言之,拷贝函数在变量初始化赋值时将会被调用。2,3中拷贝函数是在1的基础上衍生出来的。归根结底还是变量在初始化赋值时调用拷贝函数。
4 不会调用拷贝函数的情况
void main(){
NBAPlayer n("Derric Rose",29);
NBAPlayer n2("Wade",30);
//这种情况 不会调用拷贝函数
n2 = n;
system("pause");
}
5 浅拷贝
class NBAPlayer{
private:
char *name;
int age;
public:
NBAPlayer(char*name, int age){
this->name = (char*)malloc(100);
strcpy(this->name,name);
this->age = age;
cout << "有参构造函数" << endl;
}
NBAPlayer(const NBAPlayer &obj){
this->name = obj.name;
this->age = obj.age;
cout << "拷贝构造函数" << endl;
}
~NBAPlayer(){
cout << "析构函数"<< endl;
free(this->name);
}
void myPrint(){
cout << name << "," << age << endl;
}
};
void func(){
NBAPlayer n1("McGready",38);
NBAPlayer n2 = n1;
n2.myPrint();
}
void main(){
func();
system("pause");
}
运行后将会打印
有参构造函数
拷贝构造函数
McGready,38
析构函数
析构函数
然后程序会崩溃,因为在n1调用析构函数释放name后,n2在调用析构函数时,name将会为空。也就是说n1和n2操作的是同一个对象。
6 深拷贝
其他代码一样 只是在拷贝函数中把属性的值拷贝了一份
NBAPlayer(const NBAPlayer &obj){
int len = strlen(obj.name);
this->name = (char*)malloc(len+1);
//拷贝属性值
strcpy(this->name,obj.name);
this ->age = obj.age;
cout << "拷贝构造函数" << endl;
}
在此执行,运行结果一样,但是将不会报错。