C++>类与对象,类的初始化,类的访问及封装,类的实例化,类的大小,类的6个默认构造函数,构造函数,运算符重载,类与友元,内部类,this指针

C++是基于面相对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。所以类与对象是C++重要的知识点,下面在此总结。

c语言中,结构体只能定义变量,在c++中,结构体不仅可以定义常量,也可以定义函数。
类中的元素称为类的成员;类中的数据称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数。

1>类的声明与定义

1.定义格式
class  className
{
	//类体:由成员函数和成员变量组成
};   //分号很重要
2.类的声明与定义有两种方式

(1)声明与定义全在类体中。
成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
(2)声明放在.h文件中,定义放在.cpp文件中。
//不在类体内的定义格式

void  Person :: showlnfo()
{
	cout<<_name<<" "<<_sex<<" "<<_age<<endl;
}

2>类的初始化

1.构造函数

为了方便与默认构造函数对比,写在了后面。

2.初始化列表
//初始化列表
Date(int year, int month, int day)
	: _year(year)
	, _month(month)
	, _day(day)
{}

(1)每个成员变量在初始化列表中只能出现一次(只能初始化一次)。
(2)以下成员必须放在初始化列表进行初始化:引用成员变量const成员变量类类型成员(该类没有默认构造函数)。
(3)尽量用初始化列表进行初始化,因为不管是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
(4)成员变量在类中的声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

3.声明时初始化

C++11支持非静态成员变量在声明时直接初始化

private:
	int a = 10;
4.static静态成员的初始化

(1)定义
声明static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。
(2)特性
"1"静态成员为所有类对象所共享,不属于某个具体对象。
"2"静态成员变量必须在类外定义,定义时不添加static关键字。

int Test::_scout=0;

"3"类静态成员即可用"类名::静态成员"或者"对象.静态成员"来访问。
"4"静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
"5"静态成员的类和普通成员一样,也有public,protected,private访问级别,也可以具有返回值,const修饰符等参数。

3>类的访问及其封装

1.访问限制符

(1)C++的封装方式:用类将对象的属性与方法结合在一起,让对象更加完善,通过访问权限的选择性将其提供给外部用户使用。
(2)public修饰的成员在程序的任何地方都可以被访问,就是公共变量的意思,不需要通过成员函数就可以由类的实例直接访问。
(3)protected(保护)修饰的成员在类内和子类可直接访问,也就是说,基类中有protected成员,子类继承于基类,那么也可以访问基类的protected成员;private(私有)修饰的成员只有类内可直接访问,私有的,类的实例要通过成员函数才可以访问,这个可以起到信息隐藏的作用。
(4)访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止。
(5)class的默认访问权限为private,struct为public(因为struct要兼容c)。这里会有C++中struct和class的区别:C++需要兼容C语言,
所以C++中的struct可以当成结构体去使用,另外C++中的struct还可以用来定义类,和class的定义是一样的,区别是struct的成员默认访问方式是public,class的默认访问方式是private。
(6)访问限制符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。

2.封装

封装本质上是一种管理,将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅外公开接口和对象进行交互。
我们使用类的数据和方法都封装了一下,不想给别人看到的,我们用protected/private把成员封装起来,开放一些共有的成员函数对成员合理访问。

4>类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员,需要使用 :: 作用域解析符指名成员属于哪个类域。

void  Person :: PrintPersonInfo()
{
	cout<<name<<"  "<<gender<<"  "<<age<<endl;
}

5>类的实例化

用类类型创建对象的过程,称为类的实例化。类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来储存它。
一个类可以实例化出多个对象,实例化出的对象,占用实际的物理空间,储存类成员变量。

void test( )
{
Person man;
man._name="jack";
man._gender="MALE";
man._age=19;
man._showlnfo( );
}

6>类的大小

一个类的大小,实际就是该类中"成员变量之和,当然也要进行内存对齐,注意空类的大小为1,大小与构造函数无关,如果类内有内容1就失效了。

类的6个默认成员函数

任何一个类都会生成6个默认成员函数。构造函数,析构函数,拷贝构造函数,赋值重载,取地址重载(普通对象和const对象)。

1>初始化和清理

1.构造函数

构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次,构造函数没有返回类型,构造函数可以被重载。构造函数可以使内联函数,构造函数同析构函数没有返回值也不能用void修饰。

class  Date
{
public:
	Date(int year, int monrlth , int day)
	{ 
		_year = year ;
		_month = month;
		_day = day;
	}     //这种写法只能称为赋初值
//因为初始化只能初始化一次,而构造函数体内可以多次赋值。
private:
	int _year;
	int _month;
	int _day;
};

(1)默认构造函数
在类中,如果用户没有定义构造函数,编译器将会生成无参的默认构造函数。无参构造函数和全缺省构造函数都称为默认构造函数(默认构造函数只能有一个)。

//无参构造函数
Date()
{}  
//全缺省构造函数
Date()
{
	_year = 1900 ;
	_month = 1 ;
	_day = 1;
}

(2)explicit关键字
构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,explicit构造函数还可以用来防止隐式转换的。在某些情况下,隐式转换却违背了我们的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用,不能作为类型转换操作符被隐含的使用。

class Date1
{
public:
	Date1(int year)
		: _year(year)
{}
private:
	int _year;
	int _month;
	int _day;
};
class Date2
{
public:
	explicit Date2(int year)
		: _year(year)
	{}
private:
	int _year;
	int _month;
	int _day;
};
void TestDate()
{
	Date1 d=12018;	//隐式调用其默认构造函数,成功
	Date2 d2=2019;	//报错,不能隐式调用
	Date2 d2(2019);	//显式调用编译成功
}
2.析构函数

与构造函数功能相反,析构函数是完成对象的销毁的,局部对象销毁工作是由编译器完成的。在对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。
特点
"1"析构函数名是在类名前加一个’~’。
"2"无参数无返回值。
"3"一个类有且只有一个析构函数。若未显式定义,则系统自动生成默认的析构函数。
"4"对象生命周期结束,C++编译系统自动调用析构函数。

2>拷贝构造函数

构造函数:只有单个形参,该形参是对类类型对象的引用(一般用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

Date(const Date& d)
{ 
	_year = d._year;
	_month = d._month;
	_day = d.day;
}

(1)拷贝构造函数是构造函数的一个重载形式。
(2)拷贝函数的参数只有一个且必须引用传参,使用传值方式会引发无穷递归调用。
(3)若未显示定义,系统会生成默认的拷贝构造函数。默认的拷贝构造函数对象按内存储字节顺序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。对于一些类浅拷贝无法完成拷贝,需要深拷贝去完成拷贝。

3>取地址重载(赋值运算符重载)

1.概念

对于自定义类型的对象,编译器不支持在该对象上直接进行一些运算符的操作,需要通过某种方式,让编译器支持自定义类型对象的一些运算符重载。
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数。
函数原型:返回值类型 operator操作符(参数列表)
函数名字为:关键字operator后接需要重载的运算符符号。

2.注意

(1)不能通过连接其他符号来创建新的操作符,比如:operator@(C++中没有@)。
(2)重载操作符必须有一个类类型或者枚举类型的操作数。
(3)对于内置类型的操作符,其含义不能改变,例如:内置类型的+,不能改变其含义。
(4)作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参。
(5) “.*”,"::",“sizeof”,"?:",". "以上5个运算符不能重载。

const 修饰的成员函数

将const修饰的类成员函数称之为const成员函数,const加在成员函数后面,const成员函数的成员变量不允许被修改(const实际修饰this指针指向的对象,保证调用这个const成员函数的对象在函数内不会被改变。
1>const对象可以调用其它的const函数。
2>非const对象可以调用非const成员函数和const成员函数。
3>const成员函数可以调用其它的const成员函数。
4>非const成员函数内可以调用其它的const成员函数和非const成员函数。

友元

1>友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
1.友元函数可以访问类的私有成员但不是类的成员函数。
2.友元函数不能用const修饰。
3.友元函数可以定义在类的任何地方,不受类访问限定符限制。
4.一个函数可以是多个类的友元函数。
5.友元函数和普通函数的调用和原理相同。

2>友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类的非公有成员。
1.友元关系是单向的不具有交换性。
2.友元关系不能传递。

内部类

1>定义

如果一个类定义在另一个类的内部,这个类就叫做内部类。

2>注意

1.内部类是一个独立的类,他不属于外部类,更不能通过外部类的对象去调用内部类,外部类对内部类没有任何的优越访问权限。
2.内部类就是外部类的友元类。内部类可以通过外部类的对象参数来访问外部类中的所有成员。
3.特点
(1)内部类可以直接定义在外部类的public、protect、private。
(2)内部类可以直接访问外部类的static、枚举成员不需要外部类的对象/类名。
(3)sizeof(外部类)=外部类的大小,和内部类没有任何关系。

this指针

一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。对各成员的访问均通过this进行。
this指针是类的一个自动生成、自动隐藏的私有成员,它存在于类的非静态成员函数中,指向被调用函数所在的对象。全局仅有一个this指针,当一个对象被创建时,this指针就存放指向对象数据的首地址。

this指针的使用

1.在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;
2.当参数与成员变量名相同时使用this指针,如this->n = n (不能写成n = n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值