【类与对象上篇】

类与对象

    • 前言:
  • 一、面向过程和面向对象初步认识
  • 二、类的引入
  • 三、类的定义
  • 四、类的访问限定符及封装
    • 访问修饰符
    • 类的封装
  • 五、类的作用域
  • 六、类的实例化
  • 七、类成员函数的this指针

前言:

	cpp在C语言变成理念不同点就在于,c是面向过程的,cpp是面向对象的,所以c++的
与对象知识点相当重要!!!

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

用c语言解决一个问题,考虑的是解决这个问题需要什么步骤来完成,而c++考虑的则是解决这个问题需要几个对象参与完成。
就拿吃饭来说
【类与对象上篇】_第1张图片
C语言需要将吃饭分成:人拿碗、勺子,人盛饭,人筷子夹菜,人吃菜,5个步骤来完成;
c++则是:确定对象:筷子,碗,饭菜,人,勺子,由5个对象交互完成吃饭的动作。

二、类的引入

c++中的类其实就是c语言中的结构体struct,只不过在C++中struct中不光可以定义变量,还可以定义函数。

sturct arithmetic
{
	int add(int x,int y)
	{
		int sum=x+y;
		return sum;
	}
	int multiplication(int x,int y)
	{
		return x*y;
	}
	int sum=0;
};
int main()
{
	arithmetic.add(3,4);
	arithmetic.multiplication(5,5);
	return 0;
}

不过在c++中我们通常用class代替。

三、类的定义

class ClassName
{
//类体,成员变量和成员函数组成
};//此处要加 ';'

class为类的关键字,ClassName为类名,类体中的内容为类的成员,类体中的变量称为类的属性或者成员变量,类体中的函数称为类的方法或者成员函数。
类的定义两种方法:
一种将类的方法声明和定义都放在类体中

class preson
{
public:
	void showProperty()
	{
		cout<<"姓名;"<

第二种是类的方法.cpp文件中实现(我们平时尽量使用第二种)

.cpp
void preson::showProperty()//类名前要+类名::
	{
		cout<<"姓名;"<

我们在从语言中都不是将函数和变量定义在一起的,但是c++中变量和方法在同一个类中,方法中有时候需要调用属性,请看下面这种情况。

class Date
{
pubilic:
	void DateIniti(int year,int month,int day)
	{
		year=year;  //这里的变量那个是成员变量,那个是形参?分不清
		month=month;
		day=day;
	}
private:
	int year;
	int month;
	int day;
}

所以我们为了区分都是这样定义成员变量


	int _year;    //或者  my+变量名
	int _month;
	int _day;

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

访问修饰符

类一共有三个访问限定符:
【类与对象上篇】_第2张图片
1.被private和protected修饰的成员在类的外面不能被访问
2.被public修饰的成员在类外面可以被访问。
3.一个修饰符的作用域是从修饰符后面开始一直到下一个修饰符出现为止,如果没有修饰符就到 ‘ } ’ 结束
4.class的默认访问权限是private,struct的默认访问权限是public,因为c中的struct是没有访问限制的,c++要兼容c所以默认访问权限是public。

类的封装

概念:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

五、类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 ::

.cpp
void preson::showProperty()//类名前要+类名::
   {
   	cout<<"姓名;"<

作用域操作符指明成员属于哪个类域。

六、类的实例化

类的定义就好像是一份设计图纸一样,并没有被拿来做具体的事情,类的实例化就好像按照图纸给的模板设计出来看得到摸得着的实物。
【类与对象上篇】_第3张图片
用类类型创建对象的过程,称为类的实例化
一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

class Date
{
pubilic:
	void DateIniti(int year,int month,int day)
	{
		_year=year; 
		_month=month;
		_day=day;
	}
	int _year;
	int _month;
	int _day;
}
int main()
{
	Date._year;//error:因为Date还没有实例化,因为类没有实际空间
	Date d1;  //此处就是类的实例化。
	return 0;
}

我们刚提到,一个类可以创建多个对象,那么每次创建对象都在为对象中的成员开空间,就好像成员变量相当于住房小区中卧室,每个家庭有每个家庭的卧室,小区中的健身器材就没必要人人都有一份了。
【类与对象上篇】_第4张图片

// 类中既有成员变量,又有成员函数
class A1 {
public:
    void f1(){}
private:
    int _a;
};

class A2 {
public:
   void f2() {}
};

// 类中什么都没有---空类
class A3
{};
int mian()
{
	cout<

运行结果:4,1,1
首先说明一点c++中的类计算大小也是要内存对齐的
1.类的第一个成员在内存偏移量为0出开始存储
2.其他成员一次从上一个成员后面的位置找自己的对齐数的倍数初开始存储
注意:对齐数=编译器默认对齐数与该变量字节数比较的较小的一个。
3.所有成员一次在内存中安排完了之后,在内存中的字节数是不是成员最大对齐数的整数倍。

七、类成员函数的this指针

首先我们来看一个日期类的实现与调用

class Date
{
pubilic:
	void Initi(int year,int month,int day)
	{
		_year=year; 
		_month=month;
		_day=day;
	}
	void print()
	{
		cout<<_year<<"年"<<_month<<"月"<<_day<<"日"<

运行结果: 2023年2月7日 2023年2月8日
那么问题来了,编译器在使用Init方法的时候是怎么知道_year,_month,_day是d1或者是d2的成员变量呢。
原因是C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。

	void Initi( Date* this, int year,int month,int day)
	{
		thils->_year=year;   //只不过这里的Date* this和this->都不需要我们自己添加,
		this->_month=month;//都是编译器自动完成的,手动加上会报错。
		this->_day=day;
	}

this指针的特性

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

【面试题】
this指针存在哪里?
答案:this存在栈中,因为它是形参。
this指针可以为空吗?
答案:看具体情况
下面我们看几组代码

class A
{
public:
 void Print()
 {
 cout << "Print()" << endl;
 }
private:
 int _a;
};
int main()
{
	A* p = nullptr;  //编译器不报错,因为p->Print()不是p的解引用行为,Print方法不在对象中。
	p->Print();
	return 0;
}

运行结果:Print()

class A
{
public:
    void PrintA()
    {
        cout << _a << endl;//此处的this是空指针,它解引用了成员变量_a;
    }
private:
    int _a;
};
int main()
{
    A* p = nullptr;
    p->PrintA();
    return 0;
}

运行结果:运行崩溃

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