当前位置:   article > 正文

Week8-C++基础3(构造函数、静态成员函数和变量、运算符重载学习)_w8wja8c++yuk51k

w8wja8c++yuk51k

一、构造函数及析构函数
1、构造函数:没有返回值 没有void,类名相同,可以发生重载,可以有参数2、析构函数:没有返回,没有void ,函数名称: ~类名,不可以发生重载,不可以有参数
①按照构造函数的类型分类-----默认/无参构造函数、有参构造函数还有拷贝构造函数
②按照构造函数调用方法分类-----括号法调用、显示法调用
具体示例如下;

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Person
{
public: //构造和析构必须写在public下才可以调用到

	Person() //默认 、 无参构造函数
	{
		cout << "默认构造函数调用" << endl;
	}

	Person(int a)
	{
		cout << "有参构造函数调用" << endl;
	}

	//拷贝构造函数
	Person(const Person& p)
	{
		m_Age = p.m_Age;
		cout << "拷贝构造函数调用" << endl;
	}

	~Person()
	{
		cout << "析构函数调用" << endl;
	}

	int m_Age;
};


void test01()
{
	//构造函数调用方式
	//括号法调用
	Person p1(1); //有参
	p1.m_Age = 10;
	Person p2(p1); //拷贝
	cout << "p2的年龄" << p2.m_Age << endl;

	Person p3; //默认构造函数 不要加()   Person p3(); //编译器认为这行是函数的声明


	//显示法调用
	Person p4 = Person(100);
	Person p5 = Person(p4);

	Person(100); //叫匿名对象 ,匿名对象特点,如果编译器发现了对象是匿名的,那么在这行代码结束后就释放这个对象

	//不能用拷贝构造函数 初始化匿名对象
	//Person p6 = Person(p5); //如果写成左值,编译器认为你写成 Person p5; 对象的声明,如果写成右值,那么可以


	Person p7 = 100; //相当于调用了 Person p7 = Person(100) ,隐式类型转换
	Person p8 = p7; // 相当于  Person p8 = Person(p7);
}


int main() {

	test01();

	system("pause");
	return EXIT_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

运行结果如图
在这里插入图片描述
3、构造函数的调用规则
①如果提供了有参的构造,那么系统就不会提供默认的构造了,但是会提供拷贝构造
②如果提供了拷贝构造函数,那么系统就不会提供其他的构造函数了
4、深拷贝与浅拷贝
①系统默认提供的拷贝构造 会进行简单的值拷贝
②如果属性里有指向堆区空间的数据,那么简单的浅拷贝会导致重复释放内存的异常,解决上述问题,需要我们自己提供拷贝构造函数,进行深拷贝
5、其他补充
①初始化列表:在构造函数后面 + : 属性(值、参数), 属性(值、参数)…

Person(int a, int b, int c) : m_A(a), m_B(b), m_C(c)
	{}
  • 1
  • 2

②explicit关键字 作用:防止构造函数中的隐式类型转换
③new 运算符 和 delete运算符(new类似于malloc,delete类似于free),具体使用代码如下

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Person
{
public:
	Person()
	{
		cout << "默认构造调用" << endl;
	}

	Person(int a)
	{
		cout << "有参构造调用" << endl;
	}

	~Person()
	{
		cout << "析构函数调用" << endl;
	}

};

void test01()
{
	//Person p1;  栈区开辟

	Person* p2 = new Person; //堆区开辟

	//所有new出来的对象 都会返回该类型的指针
	//malloc不会调用构造吗  new会调用构造
	delete p2;

}

void test02()
{
	void* p = new Person(10);
	//当用void* 接受new出来的指针 ,会出现释放的问题
	delete p;
	//无法释放p ,所以避免这种写法
}

void test03()
{
	//通过new开辟数组 一定会调用默认构造函数,所以一定要提供默认构造
	Person* pArray = new Person[10];
	//Person pArray2[2] = { Person(1), Person(2) }; //在栈上开辟数组,可以指定有参构造


	//释放数组 delete []
	delete[] pArray;
}

int main() {

	//test01();

	//test02();

	test03();

	system("pause");
	return EXIT_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

二、静态成员变量和静态成员函数
1、 静态成员变量
① 编译阶段分配内存
② 所有对象共享数据
③ 有权限控制
④ 类内声明 类外初始化
2、 静态成员函数
① 可以访问静态成员变量,不可以方法普通成员变量
② 普通成员函数 都可以访问
③ 静态成员函数也有权限
④ 可以通过对象访问,也可以通过类名进行访问
具体代码示例如下

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Person
{
public:
	Person()
	{
		//m_Age = 10;
	}

	static int m_Age; //加入static就是 静态成员变量 ,会共享数据
	//静态成员变量,在类内声明,类外进行初始化

	//静态成员变量 也是有权限的
	int m_A;

	//静态成员函数
	//不可以访问  普通成员变量
	//可以访问 静态成员变量
	static void func()
	{
		//m_A = 10;
		m_Age = 100;
		cout << "func调用" << endl;
	};
	//普通成员函数 可以访问普通成员变量,也可以访问静态成员变量
	void myFunc()
	{
		m_A = 100;
		m_Age = 100;
	}
private:
	static int m_other; //私有权限 在类外不能访问

	static void func2()
	{
		cout << "func2调用" << endl;
	}
};
int  Person::m_Age = 0; //类外初始化实现
int  Person::m_other = 10;


void test01()
{
	//1 通过对象访问属性
	Person p1;
	p1.m_Age = 10;

	Person p2;
	p2.m_Age = 20;

	cout << "p1 = " << p1.m_Age << endl; //10 或者 20? 20
	cout << "p2 = " << p2.m_Age << endl; //20
	//共享数据

	//2 通过类名访问属性
	cout << "通过类名访问Age" << Person::m_Age << endl;
	//cout << "other = " << Person::m_other << endl; //私有权限在类外无法访问

	//静态成员函数调用
	p1.func();
	p2.func();
	Person::func();

	//静态成员函数 也是有权限的
	//Person::func2();

}

int main() {

	test01();

	system("pause");
	return EXIT_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

运行结果如图
在这里插入图片描述
3、this指针的使用
① 指针永远指向当前对象
② 解决命名冲突
③ *this 指向对象本体
④ 非静态的成员函数才有this指针
4常函数和常对象
① 常函数 void func() const {} 常函数
② 常函数 修饰是this指针 const Type * const this
③ 常函数 不能修改this指针执行的值
④ 常对象 在对象前 加入 const修饰 const Person p1
⑤ 常对象 不可以调用普通的成员函数
⑥ 常对象 可以调用常函数
⑦ 用mutable修饰的关键字是在常函数可以修改的
5、友元(friend)
① 全局函数做友元函数
(全局函数写到 类中做声明 并且最前面写关键字 friend)
② 让整个类 做友元类
( friend class 类名 )
( 友元类 是单向,不可传递的)
③ 让成员函数做友元函数
( friend void goodGay::visit();)
三、运算符重载(举单一例子)
1、加号运算符重载
① 如果想让自定义数据类型 进行+运算,那么就需要重载 + 运算符
② 在成员函数 或者 全局函数里 重写一个+运算符的函数
③ 函数名 operator+ () {}(其他运算符的话把+改掉)
④ 运算符重载 也可以提供多个版本
具体代码示例如下

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Person
{
public:
	Person() {};
	Person(int a, int b) :m_A(a), m_B(b)
	{}

	//+号运算符重载 成员函数 二元
	/*Person operator+ ( Person & p)
	{
	Person tmp;
	tmp.m_A = this->m_A + p.m_A;
	tmp.m_B = this->m_B + p.m_B;
	return tmp;
	}*/

	int m_A;
	int m_B;
};

//利用全局函数 进行+号运算符的重载
Person operator+ (Person& p1, Person& p2) //二元  p1 + p2   
{
	Person tmp;
	tmp.m_A = p1.m_A + p2.m_A;
	tmp.m_B = p1.m_B + p2.m_B;
	return tmp;
}

Person operator+ (Person& p1, int a) //二元
{
	Person tmp;
	tmp.m_A = p1.m_A + a;
	tmp.m_B = p1.m_B + a;
	return tmp;
}


void test01()
{
	Person p1(10, 10);
	Person p2(10, 10);

	Person p3 = p1 + p2; // p1 + p2  从什么表达式转变的? p1.operator+(p2)  operator+(p1,p2)
	Person p4 = p1 + 10; //重载的版本
	cout << "p3 的 m_A: " << p3.m_A << "  m_B: " << p3.m_B << endl;

	//operator+(p1, p2);

}

int main() {

	test01();

	system("pause");
	return EXIT_SUCCESS;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

运行结果如图
在这里插入图片描述
欢迎关注技术公众号,获取更多软件学习干货!
在这里插入图片描述

我们能为你提供什么?
技术辅导:C++、Java、嵌入式软件/硬件
项目辅导:软件/硬件项目、大厂实训项目
就业辅导:就业全流程辅导、技术创业支持
对接企业HR:培养输送优质性人才

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/806811
推荐阅读
相关标签
  

闽ICP备14008679号