目录
? ? ?struct和class的唯一区别在于默认的访问权限不同
? ? ?struct默认权限是公共 public
? ? ?class默认权限是私有 private
struct C1
{
int a;
};
class C2
{
int a;
};
struct C1 c1;
c1.a=100;//在struct默认权限为公共,因此可以访问
C2 c2;
c2.a=100;//在class默认权限为私有,因此不能访问
? ? ?优点1:将所有成员属性设置为私有,可以自己控制读写权限
? ? ?优点2:对于写权限,我们可以检测数据的有效性
#include<iostream>
using namespace std;
class Person
{
//姓名设置可读可写
void setName(string name)
{
_name=name;
}
void getName()
{
return _name;
}
//年龄设置只读
int getAge()
{
return _age;
}
//偶像设置只写 外界无法访问
void setIdol(string idol)
{
_idol=idol;
}
private:
string _name;//可读可写
int _age=18;//只读
string _idol;//只写
};
? ? ?在生活中我们购买电子产品都会有出厂设置,我们如果不用了也要删除信息保证自己的隐私安全,C++的面向对象来源于生活,每个对象也会有初始化设置以及对象销毁前的清理数据的设置。
? ? ?一个对象或者变量没有初始状态,使用后果很未知,用完不进行清理。也有安全问题。C++利用构造函数和析构函数解决问题,这两个函数被编译器自动调用,完成对象的初始化和清理工作。
如果我们自己不实现这两个操作,编译器会提供,但编译器提供的构造函数和析构函数是空实现
? ? ?构造函数:主要用于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用,当然也可以自己进行实现。
? ? ? 析构函数:主要用于对象销毁前系统自动调用,执行清理工作
类名(){}
1.构造函数没有返回值,不用写void
2.函数名称与类名相同
3.构造函数可以有参数,因此可能有重载
4.程序在调用对象时会自动调用该函数,且只调用一次
~类名(){}
1.构造函数没有返回值,不用写void
2.函数名称与类名相同,在名称前加上~
3.构造函数不可以有参数,因此不可能有重载
4.程序在对象销毁前会自动调用该函数,且只调用一次
#include<iostream>
using namespace std;
class Person
{
public:
//构造函数
Person()
{
cout<<"Person 构造函数的调用"<<endl;
}
//析构函数
~Person()
{
cout<<"Person 析构函数的调用"<<endl;
}
}
int main()
{
Person p;//在栈上的数据,之后释放该对象
}
? ? ?输出:
Person 构造函数的调用
Person 析构函数的调用
? ? ?可以发现,我们只是创建了一个对象,并没有实现函数,这肯定是构造函数和析构函数被系统自动调用了啊,这两个函数都是必须有的,如果我们自己不提供,编译器给你提供,但都是空实现。
? ? ?分类:
? ? ? ? ? ?按参数分为:含参构造和无参构造 无参构造又称为默认构造函数
? ? ? ? ? ?按类型分为:普通构造和拷贝构造
? ? ?调用:
? ? ? ? ? ? 括号法
? ? ? ? ? ? 显示法
? ? ? ? ? ? 隐式转换法
#include<iostream>
using namespace std;
class Person
{
public:
//构造函数 普通构造
Person()
{
cout<<"Person 无参(默认)构造函数的调用"<<endl;
}
Person(int a)
{
cout<<"Person 含参构造函数的调用"<<endl;
}
//拷贝构造函数
Person(const Person &p)
{
cout<<"拷贝构造函数的调用"<<endl;
age=p.age//将传入对象上的所有属性,拷贝到另一个人身上
}
//析构函数
~Person()
{
cout<<"析构函数的调用"<<endl;
}
}
//调用
void test()
{
//括号法
Person p1;//默认构造函数的调用
Person p2(10);//含参构造函数的调用
Person p3(p2);//拷贝构造函数的调用
//显示法
Person p1;
Person p2=Person(10);//Person(10)为匿名对象 特点:当前行命令执行结束后,系统会马上回收匿名对象
Person p3=Person(p2);//不能利用拷贝构造函数来初始化匿名对象,编译器会认为Person(p3)===Person p3;导致重定义
//隐式转换法
Person p4=10;//相当于Person p4=Person(10);
Person p5=p4;
}
int main()
{
test();
}
? ? ?C++拷贝构造函数通常是这三种情况:
1.使用一个已经创建完的对象来初始化一个新对象
2.值传递的方式给函数参数传值
3.以值方式返回局部对象
? ? ?以上面的class为例
1.使用一个已经创建完的对象来初始化一个新对象
Person p1;
Person p2(p1);
?2.值传递的方式给函数参数传值
void doWork(Person p)
{
}
void test()
{
Person p;//调用默认构造函数
doWork(p);//值传递 实参传给形参,调用拷贝构造函数
}
3.以值方式返回局部对象
Person doWork()//根据p1 创建出一个新对象返回 这肯定要调用拷贝构造函数
{
Person p1;
return p1;
}
void test()
{
Person p=doWork();
}