C++——类和对象(上)

目录

一、面向过程和面向对象的初步认识

二、引入类

三、类的定义

四、类的访问限定符和封装

1.访问限定符

2.封装     

五、类的作用域

六、类的实例化

七、类的大小

八、this指针


一、面向过程和面向对象的初步认识

C语言是面向过程的,分析出求解问题的方法,调用函数解决问题。

C++是面向对象的,将一件事分出不同的对象,依靠对象间的交互完成。

二、引入类

C语言结构体不支持成员函数,但C++结构体支持。C++的class与struct本质没有区别,唯一区别在于默认时class的成员访问属性为私有,struct为公有。

C++定义结构体类型的变量时,类型名可以不加struct。

三、类的定义

struct的升级版——class

class className
{
	//类体:成员函数(方法)和成员变量(属性)
};

class是定义类的关键字。className是类名,{}里是类的主体。注意}最后的分号不能省略

类中的内容称为类的成员:变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。

c++的类可以函数在上,变量在下。或者变量在上,函数在下。c++把类看作整体,搜索的时候在整个类里找。顺序不重要,不影响效率。

c语言习惯先定义或者声明再使用。c语言每个变量和函数之间没有必定的关联,是独立的。

class算不算一个域?

算。

那能不能和命名空间一样用 " ::  "域作用限定符直接去访问类里面的成员?

比如:Person ::_age=1;//错的

1.成员变量不能。因为class和struct一样,只是定义了一个类型,还没有创建实体,没有开辟空间。所以不能访问。就算把成员变量改成公有的,也不能通过类直接访问。类只是声明,还没有实体。

2.成员函数不能直接通过类访问。成员函数的调用需要传递this指针。后面说。

类的定义方法:

1.声明和定义一起写:但是直接在类里面定义成员函数,编译器可能会把它当做内联函数。

2.类的声明在.h文件中写,成员函数的定义分离出来在.cpp写。

声明和定义分离的意义:方便阅读。看看到底有哪些方法。

  • .h里面不同类里的成员函数可以同名,因为在不同类域,也不构成函数重载(函数重载需要在同一个域)。在.cpp里定义成员函数时,要使用域作用限定符指定类域。

例:

C++——类和对象(上)_第1张图片

 C++——类和对象(上)_第2张图片

  • 成员函数里的变量先在局部找,因为指定了类域,再去类域找,再去全局找。

  • 声明成员变量的时候可以加_,这样好区分参数和成员变量。

例:日期类:不用_的话,有点难分清谁是谁

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

四、类的访问限定符和封装

1.访问限定符

public(公有) protected(保护) private(私有)

  1. public的成员在类外可以直接被访问
  2. protected和private修饰的成员在类外不能直接被访问(现阶段先当保护和私有一样)
  3. 限定符的作用域是从该限定符到下一个限定符。或者没有下一个限定符,作用域就是该限定符到类结束。
  4. 访问限定符只限制外面的访问,类里面不限制访问   

struct和class的区别

  • c语言结构体不支持成员函数。
  • c++的class和struct没有本质区别。如果不写访问限定符,struct默认是公有的,class默认是私有的。
  • 在继承和模板参数列表位置,struct和class也有区别,后续再学。


2.封装     

面向对象的三大特性:封装、继承、多态。

只能通过规范的方式访问数据就是封装。

c++把数据和方法都放在了类里,而c语言是分开的。在类里用访问限定符修饰成员,想让类外使用就公有,不想被类外访问就私有。封起来是为了更好的管理。

c++要访问数据只能调用函数,要增删查改数据只能调用公有的函数。 

例:st.Top();

c语言规范一点应该也是调用函数访问数据,但也能不规范操作。

例:

规范:StackTop(&st);       

不规范:st.a[st.top-1];  //      这里要看top初始化是0还是-1。0就是插入,++,top就是最后一个数据的下一个位置。如果top初始化是-1,那top就是最后一个数据的下标。所以说,容易弄错下标,仔细看初始化才能不搞错。          

                                                                C++——类和对象(上)_第3张图片c语言的数据和方法是分开的,访问很自由,但是可能会出错。     

五、类的作用域

类是一个域,类的所有成员都在类的作用域中。在类外定义成员函数 ,需要用"::"域作用限定符指定域。

                        

六、类的实例化

用类创建对象,称为类的实例化

访问类的成员:

1.通过对象访问类的公有成员

ae5059a32e004e3ab8af122c52442502.png

 2.通过地址访问公有成员

C++——类和对象(上)_第4张图片

七、类的大小

class A
{
public:
	void Func()
	{
		cout << "hh" << endl;
	}

//private:为了方便查看,先用public吧
	int _a;
};
int main()
{
	A a1;
	a1._a = 1;
	a1.Func();

	A a2;
	a2._a = 2;
	a2.Func();

	return 0;
}

a1和a2的_a地址不一样,但是a1,a2调用的函数是同一个函数(函数定义好,谁来调都是调这个函数)。数据存储到每个对象里,函数地址默认就放到公共代码区,对象里面连公共区域地址都不用存。                                                                                          

常量区或者叫代码段,常量和编译后的代码指令地址都存在这里面。对于编译器来讲,放在常量区就是常规操作,根本不用再另外存函数地址来找函数。 

所以说类的大小只计算成员变量的就行,对象里不存函数地址。算的方法跟结构体一样,内存对齐(前面写过博客哦)。

类的大小可以sizeof(类名),也可以sizeof(对象)

类里面没有成员变量,类的大小是多少?

不是0,是1字节。(确实没想到)。这一个字节是为了标识对象存在,不存储数据。不存数据也得开个空间,好取地址,不然我们的对象能是空气对象吗。

class A1
{
public:
	void Func()
	{
		cout << "hh" << endl;
	}
};

class A2
{
	
};


int main()
{
	A1 a1;
	cout << sizeof(a1) << endl;

	A2 a2;
	cout << sizeof(a2) << endl;


	return 0;
}

47585f0f471743cc8f4bcccf032d819f.png

八、this指针

既然相同类,不同对象调用的函数是同一个,那为什么同类型的两个对象调同一个函数没传参也会出现不同结果?

class Date
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1;
	d1.Init(2022, 10, 12);
	d1.Print();

	Date d2;
	d2.Init(2022, 10, 13);
	d2.Print();//没传参奥

	return 0;
}

a40ad55122664940834c8d882747f44b.png

拿上面的Print举例

1.编译器会对Print函数进行处理,会给函数加一个隐藏的指针参数——this指针。

this是一个关键字。

C++——类和对象(上)_第5张图片

 谁调函数就传的是谁的this地址,就能访问到对象的成员变量。

2.this指针的定义和传递都是由编译器完成,我们不能操作,但是我们可以在类里面用this指针。(一般不在函数形参写出来,但是能在函数里面用)

C++——类和对象(上)_第6张图片

 3.this指针的类型:类名*const this。

复习一下const:

const在*左边,保护指针指向对象的内容不被修改。const在*右,指针指向的对象不能改变

  • const Data* p1;//const修饰*p1
  • Data const* p2;//const修饰*p2
  • Data*const p3;//const修饰p3

this指针存在哪?

this指针是形参。一般存在栈帧里面。vs进行了优化,使用ecx寄存器传递。

this指针可以为空吗?

先看例子:猜想运行结果(编译报错,运行崩溃,正常运行)

class A
{
public:
	void Print()
	{
		cout <<"Print()"<< endl;
	}

private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();//实质:Print(p)。空指针可以传递。成员函数的地址在常量区,不发生解引用空指针
	return 0;
}

d4ca7e11546f4cd6909735ff65da0041.png

class A
{
public:
	void Print()
	{
		cout << _a << endl;//实质上是这样访问_a的:p->_a。空指针解引用会运行崩溃。
	}

private:
	int _a;
};

int main()
{
	A* p = nullptr;
	p->Print();//Print(p)
	return 0;
}

C++——类和对象(上)_第7张图片

总结: 空指针可以传递,但不能解引用。

你可能感兴趣的:(C++,c++)