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、m²和m³均为回文数。

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

——11满足上述条件:11²=121,11³=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;
}

运行结果:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值