IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++之对象特性 -> 正文阅读

[C++知识库]C++之对象特性

一、构造函数:对对象成员属性做初始化。

1、语法:类名 (){ }

  • 没有返回值也不写void ;
  • 函数名称与类名相同;
  • 构造函数可以有参数,因此可以发生重载(函数名称相同,返回类型相同,参数不同,参数个数不同);
  • 程序在调用对象时候会自动调用构造函数,无须手动调用,而且只会调用一次。
class Person
{
public:
Person()//普通构造
{
cout<<"构造函数的调用"<<endl;  
}

};
 
void test01()
{
Person p;
}
int main(){
test01();
return 0;
}

2、两种分类方式:

1、按参数分:有参构造和无参构造(默认构造);

2、按类型分:普通构造和拷贝构造

//有参构造函数
class Person(){
public:
Person(int a)
{
age=a;
cout<<"person的有参构造函数调用"<<endl;
}
//拷贝构造函数
Person(const Person &p)
{
//将传入的人身上的所有属性,拷贝到我身上
age=p.age;
cout<<"Person的拷贝构造函数的调用"<<endl;
}
};

3、三种调用方法:

(1)、括号法? ? ? ? ? ? ? ?

注意:调用默认构造函数的时候不加(),不能写成Person? p1();会被编译器认为是函数的声明,不会认为在创建对象
?

(2)、显示法、

注意:单独的Person (10);被认为是匿名对象 ?特点是:当前执行结束后,系统立即会收掉匿名对象
注意:不要利用拷贝构造函数初始化匿名对象

例: Person(p3);

?编译器会认为 Person (p3)==Person p3;是对象的声明。

(3)、隐式转换法?

void test01()
{
//1、括号法
Person p1;//默认构造函数调用
Person p2(10);//调用有参构造函数 
Person p3(p2);//拷贝构造函数的调用

//2、显示法
person p1;//默认构造
Person p2=Person(10);//有参构造
Peerson p3=Person (p2);//拷贝构造

//3、隐式转换法
Person p4=10;//相当于 写了 Person p4= Person (10); 有参构造
Person p5=p4;//拷贝构造

}
int main()
{
test01();
return 0;
}

4、拷贝构造函数调用时机

(1)、使用一个已经创建完毕的对象来初始化一个新对象

(2)、值传递的方式给函数参数传值

(3)、以值方式返回局部对象

二、析构函数:对对象销毁前系统自动调用,做清理工作。

1、语法:~类名 (){ }

  • 没有返回值,也不写void ;
  • 函数名称与类名相同,在名称前加上符号~ ;
  • 析构函数不可以有参数,不可以发生重载;
  • 对象在销毁前会自动调用析构函数,而且只会调用一次。
 class Person{
public:
~Person()
{
cout<<"析构函数的调用"<<endl;
}
};
void test01()
{
Person p;
}
int main()
{
test01();
return 0;
}

编译器会强制要求实现对对象成员的初始化和清理,一般未写明时,编译器会自动生成自动调用,但内容为空,即空实现。

三、构造函数调用规则

默认情况下编译器会给一个类配置三个函数:

  • 构造函数,无参,函数体为空。
  • 析构函数,无参,函数体为空。
  • 拷贝构造函数,对属性进行值拷贝。

三个函数的调用规则:

  • 若用户定义有参构造函数,c++ 不再提供默认无参构造,会提供拷贝构造。
  • 若用户定义拷贝构造函数,c++不会再提供其他构造函数。

四、深拷贝与浅拷贝

浅拷贝:简单的赋值拷贝操作,编译器提供的拷贝构造函数里提供的操作都是浅拷贝

存在问题:如果有数据开辟在堆区,在析构函数调用时,同一块堆区的内存重复释放

解决办法:深拷贝,自己写一个拷贝构造函数

深拷贝:在堆区重新申请一块空间,做赋值操作。

大概白话理解,就是在创建对象参数的时候有些指针类型的属性创建在堆区,在有对象进行拷贝操作的时候,如果调用的时编译器自带的拷贝构造函数,就会导致两个对象的属性指向同一块内存空间,在析构释放时,拷贝对象(P2)会先释放掉指向的那块内存空间,被拷贝对象(p1)在析构释放时会要求再释放一遍,这就导致了同一块内存空间重复释放的问题,解决办法就是自己写一个拷贝构造函数,在自己写的拷贝构造函数里,把指针类型的属性数据重新开辟一块空间(深拷贝)。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
	//有参构造函数
	Person(int age, int height)
	{
		cout << "Person的有参构造函数调用" << endl;
		m_age = age;
		m_Height = new int (height);
	}
	//拷贝构造函数
	Person(const Person& p)
	{
		cout << "Person的拷贝构造函数调用" << endl;
		m_age = p.m_age;
		//m_Height = p.m_Height;由编译器提供,默认实现的浅拷贝
		m_Height = new int(*p.m_Height);//深拷贝,在堆区开辟一块新的空间,避免重复释放
	}
	//析构函数
	~Person()
	{
		if (m_Height != NULL)
		{
			delete m_Height;
			m_Height = NULL;
		}
		cout << "Person的析构函数调用" << endl;
	}

	int m_age;
	int* m_Height;
};

void test01()
{
	Person p1(18,158);
	Person p2(p1);
}
int main()
{
	test01();
	return 0;
}

五、初始化列表

对类中的属性进行初始化操作。主要在构造函数中。

语法:类名():属性1(值1),属性2(值2)........{? ? ? ? }

示例:

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
using namespace std;
class Person
{
public:
	//初始化列表①
	Person() :m_A(10), m_B(20), m_C(30)
	{
		cout << m_A << endl;
		cout << m_B << endl;
		cout << m_C << endl;
	}
	//传统初始化方式②
	Person(int a, int b, int c)
	{
		m_A = a;
		m_B = b;
		m_C = c;
	}
	//优化后的初始化列表操作③
	/*Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c)
	{

	}*/

	int m_A;
	int m_B;
	int m_C;
};


void test01()
{	//②
	Person p1(10, 20, 30);
	cout <<p1.m_A << endl;
	cout << p1.m_B << endl;
	cout << p1.m_C << endl;
	//①
	Person p2;
	cout << p2.m_A << endl;
	cout << p2.m_B << endl;
	cout << p2.m_C << endl;
	//③
	/*Person p3(100, 200, 300);
	cout << p3.m_A << endl;
	cout << p3.m_B << endl;
	cout << p3.m_C << endl;*/

}
int main()
{
	test01();
	return 0;
}

六、类对象作为类成员

B类中有对象A作成员,A为对象成员。

会先构造对象成员A的对象,再构造自身B;

析构相反,会先析构自身B,再析构对象成员A。

七、静态成员

静态成员就是在成员变量和成员函数前加上关键字stastic,称为静态成员。

分类:

  • 静态成员变量:

  1. 所有对象共享同一份数据
  2. 在编译阶段分配内存空间
  3. 类内声明,类外初始化
  • 静态成员函数:

  1. 所有函数对象共享同一个函数
  2. 静态成员函数只能访问静态成员变量

例题:寻找并输出11~999之间的数m,它满足m、m2和m3均为回文数。

——回文数:各位数字左右对称的整数。

——11满足上述条件:112=121,113=1331.

分析:模10取余的方法,从最低位开始,依次取出该数的各位数字。按反序重新构成新的数,比较与原数是否相等,若相等,则原数为回文。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
bool func(unsigned n)
{
	unsigned i = n;
	unsigned m = 0;
	while (i > 0)
	{
		m = m * 10 + i % 10;
		i /= 10;
	}
	return m == n;
}
int main()
{
	unsigned m = 11;
	for (m = 11; m < 1000; m++)
	{
		if (func(m) && func(m * m) && func(m * m * m))
		{
			cout << "m=" << m << endl;
			cout << "m*m=" << m * m<<endl;
			cout << "m*m*m=" << m * m*m<<endl;
		}
	}
	return 0;
}

运行结果:

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 18:45:50  更:2022-08-19 18:49:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 14:26:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码