目录
4.2.1 构造函数和析构函数
构造函数
没有返回值,不用写void
函数名 与类名相同
构造函数可以有参数,可以发生重载
创建对象的时候,构造函数会自动调用,而且只调用一次
析构函数 进行清理的操作
没有返回值 不写void
函数名和类名相同 在名称前面加~
析构函数不可以有参数 不可以发生重载
对象在销毁前 会自动调用析构函数 而且只会调用一次
#include <iostream>
#include <string>
using namespace std;
class person {
public:
//构造函数
//没有返回值,不用写void
//函数名 与类名相同
//构造函数可以有参数,可以发生重载
//创建对象的时候,构造函数会自动调用,而且只调用一次
person() {
cout << "person构造函数的调用" << endl;
}
//2、析构函数 进行清理的操作
//没有返回值 不写void
//函数名和类名相同 在名称前面加~
//析构函数不可以有参数 不可以发生重载
//对象在销毁前 会自动调用析构函数 而且只会调用一次
~person() {
cout << "person的析构函数的调用" << endl;
}
};
void perso() {
person p;
}
int main() {
//person i;
perso();
system("pause");
}
4.2.2构造函数的分类以及调用
1、构造函数的分类以及调用
分类
按照参数来分类 无参构造(默认构造) 有参构造
按照类型分类 普通构造函数 拷贝构造函数
1、括号法
person p1;//默认构造函数调用
person p2(10);//有参构造函数
person p3(p2);//拷贝构造函数
注意事项1
调用默认构造函数的时候,不要加()
因为下面这行代码,编译器认为是函数的声明,不会认为在创建对象
person p1();
void func();
2、显示法
person(10); //匿名对象 特点:当前行执行结束之后,系统会立即回收掉匿名对象
注意事项2
不要利用拷贝构造函数来 初始化匿名对象 编译器会认为person(p3) === person p3;
编译器会认为为对象的声明
3、隐式转化法
#include <iostream>
#include <string>
using namespace std;
//1、构造函数的分类以及调用
//分类
// 按照参数来分类 无参构造(默认构造) 有参构造
// 按照类型分类 普通构造函数 拷贝构造函数
class person
{
public:
//构造函数
person() {
cout << "person的无参构造函数的调用" << endl;
}
person(int a) {
age = a;
cout << "person的有参构造函数的调用" << endl;
}
//拷贝构造函数
person(const person &p)
{
//将传入的人身上的所有属性,拷贝到我身上
age = p.age;
cout << "person的拷贝构造函数的调用" << endl;
}
~person()
{
cout << "person的析构函数的调用" << endl;
}
int age;
};
void text01()
{
//1、括号法
//person p1;//默认构造函数调用
//person p2(10);//有参构造函数
//person p3(p2);//拷贝构造函数
//注意事项1
//调用默认构造函数的时候,不要加()
//因为下面这行代码,编译器认为是函数的声明,不会认为在创建对象
//person p1();
//void func();
//cout << "p2的年龄为:"<< p2.age << endl;
//cout << "p3的年龄为:" << p3.age << endl;
//2、显示法
person p1;
person p2 = person(10);//有参构造
person p3 = person(p2);//拷贝构造
//person(10); //匿名对象 特点:当前行执行结束之后,系统会立即回收掉匿名对象
//cout << "aaaaa" << endl;
//注意事项2
//不要利用拷贝构造函数来 初始化匿名对象 编译器会认为person(p3) === person p3;
//编译器会认为为对象的声明
//person(p3);
//3、隐式转化法
person p4 = 10;// 相当于 person p4= person(10)
person p5 = p4;
}
int main() {
text01();
system("pause");
}
4.2.3拷贝构造函数调用时机
拷贝构造函数调用时机
1、使用一个已经创建完毕的对象来初始化一个新对象
2、值传递二点方式给函数参数传值
3、值方式返回局部对象
#include <iostream>
#include <string>
using namespace std;
class person
{
public:
person()
{
cout << "person的构造函数调用" << endl;
}
person(int age)
{
Age = age;
cout << "person的有参函数调用" << endl;
}
person(const person &p)
{
Age = p.Age;
cout << "person的拷贝函数调用" << endl;
}
~person()
{
cout << "person的析构函数调用" << endl;
}
int Age;
};
//拷贝构造函数调用时机
//1、使用一个已经创建完毕的对象来初始化一个新对象
void text01()
{
person p1(20);
person p2(p1);
cout << "p2的年龄为:" << p2.Age << endl;
}
//2、值传递二点方式给函数参数传值
void dowork(person p)
{
}
void text02()
{
person p;
dowork(p);
}
//3、值方式返回局部对象
person dowork2()
{
person p1;
return p1;
}
void text03()
{
person p = dowork2();
}
int main() {
text01();
text02();
text03();
system("pause");
}
4.2.4构造函数调用规则
构造函数的调用规则
1、创建一个类,c++编译器会给每个类都添加至少三个函数
默认函数 (空实现)
析构函数 (空实现)
拷贝构造 (值拷贝)
2、 如果我们写了有参构造,编译器不再提供默认构造,依然提供拷贝构造
如果我们写了拷贝构造函数,编译器就不再提供其他的普通构造函数
#include <iostream>
#include <string>
using namespace std;
//构造函数的调用规则
//1、创建一个类,c++编译器会给每个类都添加至少三个函数
//默认函数 (空实现)
//析构函数 (空实现)
//拷贝构造 (值拷贝)
//2、如果我们写了有参构造,编译器不再提供默认构造,依然提供拷贝构造
//如果我们写了拷贝构造函数,编译器就不再提供其他的普通构造函数
class person
{
public:
person()
{
cout << "person的默认构造函数调用" << endl;
}
person(int age)
{
Age = age;
cout << "person的有参构造函数调用" << endl;
}
person(const person &p)
{
Age = p.Age;
cout << "person的拷贝构造函数调用" << endl;
}
~person()
{
cout << "person的析构函数调用" << endl;
}
int Age;
};
void text01()
{
person p;
p.Age = 18;
person p2(p);
cout << "p2的年龄为:" << p2.Age << endl;
}
void text02()
{
person p(28);
person p2(p);
}
int main() {
text01();
text02();
system("pause");
}
4.2.5深拷贝与浅拷贝
深拷贝与浅拷贝
浅拷贝带来的问题:
堆区的内存重复释放 这个问题要用深拷贝来解决
总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题
#include <iostream>
#include <string>
using namespace std;
//深拷贝与浅拷贝
//浅拷贝带来的问题:
//堆区的内存重复释放 这个问题要用深拷贝来解决
class person
{
public:
person()
{
cout << "person的默认构造函数调用" << endl;
}
person(int age,int height)
{
Age = age;
Height = new int(height);
cout << "person的有参构造函数调用" << endl;
}
//自己实现拷贝构造函数 解决浅拷贝带来的问题
person(const person &p)
{
cout << "person拷贝函数调用" << endl;
Age = p.Age;
//Height = p.Height;编译器默认实现这段代码
Height = new int(*p.Height);
}
~person()
{
//将堆区开辟的数据做释放的操作
if (Height != NULL)
{
delete Height;
Height = NULL;
}
cout << "person的析构函数调用" << endl;
}
int Age;
int *Height;
};
void text01()
{
person p1(18,160);
cout << "p1的年龄:" <<p1.Age<< "身高为:" << *p1.Height << endl;
person p2(p1);
cout << "p2的年龄:" << p2.Age <<"身高为:"<<*p2.Height<< endl;
}
int main() {
text01();
system("pause");
}
4.2.6初始化列表
初始化列表初始化属性
person(int a,int b,int c) :A(a), B(b), C(c)
{
}
person(10,20,30);
#include <iostream>
#include <string>
using namespace std;
//初始化列表
class person
{
public:
//person(int a, int b, int c)
//{
// A = a;
// B = b;
// C = c;
//
//}
//初始化列表初始化属性
person(int a,int b,int c) :A(a), B(b), C(c)
{
}
int A;
int B;
int C;
};
void text01()
{
person p(10, 20, 30);
//person p;
cout << "A = " << p.A << endl;
cout << "B = " << p.B << endl;
cout << "C = " << p.C << endl;
}
int main() {
text01();
system("pause");
}
4.2.7类对象作为类成员
当其他类的对象作为本类的成员,构造时候先构造类对象,再构造自身,析构函数运行则相反
#include <iostream>
#include <string>
using namespace std;
//类对象作为类成员
class Phone
{
public:
Phone(string pname)
{
pName = pname;
cout << " phone的构造函数调用" << endl;
}
~Phone()
{
cout << "phone的析构函数调用" << endl;
}
//手机品牌名称
string pName;
};
class person
{
public:
person(string name, string pname):Name(name),Phone(pname)
{
cout << "person的构造函数调用" << endl;
}
~person()
{
cout << "person的析构函数调用" << endl;
}
//姓名
string Name;
//手机
Phone Phone;
};
//当其他类的对象作为本类的成员,构造时候先构造类对象,再构造自身,析构
void text01()
{
person p("张三", "苹果max");
cout << p.Name << "拿着:" << p.Phone.pName << endl;
}
int main() {
text01();
system("pause");
}
4.2.8静态成员以及函数
1、静态成员
1、所有成员都共享同一数据
2、编译阶段就分配内存
3、类内声明,类外初始化操作
#include <iostream>
#include <string>
using namespace std;
//静态成员变量
class person
{
public:
//1、所有成员都共享同一数据
//2、编译阶段就分配内存
//3、类内声明,类外初始化操作
static int A;
//静态成员变量也是有访问权限的
private:
static int B;
};
int person::A = 100;
void text01()
{
person p;
cout << p.A << endl;
person p2;
p2.A = 200;
cout << p.A << endl;
}
void text02()
{
//静态成员变量 不属于某个对象上 所有兑现都共享同一份数据
//因此静态成员变量有两种访问方式
//1、通过对象进行访问
person p;
cout << p.A << endl;
//2、通过类名进行访问
cout << person::A << endl;
//cout << person::B << endl; 不可访问 类外访问不到私有的静态成员
}
int main() {
text01();
text02();
system("pause");
}
2.静态成员函数
所有对象共享同一个函数
静态成员函数只能访问静态成员变量
静态成员函数 可以访问 静态成员变量
静态成员函数 不可以访问 非静态成员变量 无法区分到底是哪个对象的成员
静态成员函数也是有访问权限的,类外访问不到私有静态成员函数
访问方式有两种:1、通过对象进行访问
2、通过类名来进行访问
#include <iostream>
#include <string>
using namespace std;
//静态成员函数
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量
class person
{
public:
//静态成员函数
static void func()
{
A = 100;//静态成员函数 可以访问 静态成员变量
//B = 100; 静态成员函数 不可以访问 非静态成员变量 无法区分到底是哪个对象的成员
cout << "静态成员函数调用" << endl;
}
static int A;//静态成员变量
int B;
//静态成员函数也是有访问权限的
private:
static void func2() {
cout << "静态成员函数调用" << endl;
}
};
//有两种访问方式
void text01()
{
//1、通过对象进行访问
person p;
p.func();
//2、通过类名来进行访问
person::func();
//p.func2();类外访问不到私有静态成员函数
}
int main() {
text01();
system("pause");
}