类与对象(一)

一、类的定义

C语言中,结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。

C++同时对struct进行了升级,把struct 升级成了类

1、结构体名称可以做类型

2、里面可以定义函数

//结构体的定义,在C++中更喜欢用class来代替
class U
{
	int a;
	char b;
	int add(int x, int y)
	{
		return x + y;
	}
};
class 定义类的关键字, 类中的元素称为 类的成员: 类中的 数据 称为 类的属性 或者 成员变量 ; 类中的 函数 称为 类的方法 或者 成员函数
  • 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
  • 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量

1.1 类的两种定义方法

1.1.1 声明和定义全部放在类体中

class U
{
public:
	int a;
	char b;
	int add(int x, int y)
	{
		return x + y;
	}
};
成员函数如果在类中定义,编译器可能会将其当成内联函数处理

1.1.2 声明定义分开,声明放在.h文件中,类的定义放在.cpp文件中

Func.h

class U
{
public:
	int a;
	char b;

	//在类里面定义的函数,默认是inline,内联函数
	int mul(int x, int y)
	{
		return x * y;
	}

	//在类里面声明,在.cpp里面定义
	int Add(int x, int y);
	int Sub(int x, int y);
};

Func.cpp

#include "Func.h"

//用'::'符号进行访问
int U::Add(int x, int y)
{
	return x + y;
}

int U::Sub(int x, int y)
{
	return x - y;
}

实际中,短小函数可以直接在类里面定义, 长一点函数声明和定义分离

一般情况定义和声明分开更好


二、类的访问限定符

2.1 访问限定符

1.public(共有)     2.private(私有)     3.protected(保护

访问限定符使用:

  • public修饰的成员在类外可以直接被访问
  • protectedprivate修饰的成员在类外不能直接被访问(protectedprivate是类似的)
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
  • class的默认访问权限为privatestructpublic(因为struct要兼容C),两者相反
    class U
    {
    public:
    	int Add(int x, int y)
    	{
    		return x + y;
    	}
    private:
    	int a;
    	int b;
    	int c;
    };

三、类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符指明成员属于哪个类域。
class U
{
public:
	int Add(int x, int y);
private:
	int a;
	int b;
	int c;
};

int U::Add(int x, int y)
{
	return x + y;
}

四、类的大小

类对象的存储方式:只保存成员变量,成员函数存放在公共的代码段

//大小:16字节
class A
{
public:
	int Add(int x, int y)
	{
		return x + y;
	}
private:
	int a;
	char b;
	double c;
};

//大小:16字节
class B
{
public:
	int a;
	char b;
	double c;
};

//大小:1字节
class C
{
public:
	int Add(int x, int y)
	{
		return x + y;
	}
};
一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐( 结构体内存对齐规则 ),注意空类( 成员只有函数 )的大小,空类比较特殊,编译器给了空类 一个字节 来唯一标识这个类。

五、this指针

C++ 编译器给每个 非静态的成员函数 增加了一个隐藏的指针参 数,让该指针(this指针)指向当前对象 ( 函数运行时调用该函数的对象 ) ,在函数体中所有成员变量的操作,都是通过该 指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成
this指针存放在栈里

 5.1 this指针的特性

class Date
{
public:

	//void Print(Date* const this)
	void Print()
	{
		//cout << this->_year << this->_month << this->_day <<endl;
		cout << _year << _month << _day << endl;
	}


	//void Creat(Date* const this, int year, int month, int day)
	//{
	//	//this指针本身不能修改,因为它是const修饰的
	//	//但是this指针指向的对象可以被修改
	//	this->_year = year;
	//	this->_month = month;
	//	this->_day = day;
	//}
	void Creat(int year, int month, int day)
	{
		//可以看到this指针的存在
		cout << this << endl;
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	Date d2;

	//d1.Creat(&d1,2022,5,17)
	d1.Creat(2022, 5, 17);
	//d2.Creat(&d2,2022,5,20)
	d2.Creat(2022, 5, 20);


	//d1.Print(&d1)
	d1.Print();
	//d2.Print(&d2)
	d2.Print();
	return 0;
}

 特性:

  • this指针的类型:类类型* const
  • 只能在“成员函数”的内部使用
  • this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针
  • this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递

 

 5.2 this指针为空的问题

下面这段代码会运行崩溃:

class A
{
public:

	//void Print(A* const this)
	void Print()
	{
		//this为空,指向a,使用空指针指向的东西,程序就会崩溃
		//cout << this->a << endl;
		cout << a << endl;
	}
private:
	int a;
};

int main()
{
	A* p = nullptr;

	//p->Print(&p)
	p->Print();

	return 0;
}

 下面这段代码会正常运行:

class A
{
public:

	//void Show(A* const this)
	void Show()
	{
		//传空指针没问题
		cout << "Show()" << endl;
	}
private:
	int a;
};

int main()
{
	A* p = nullptr;

	//类里面只有成员变量,没有成员函数
	//不用指针指向函数,可以直接调用函数,跟空指针没关系
	//p->Show(&p)
	p->Show();
	return 0;
}

 

  • 42
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 35
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cristiano777.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值