栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++(类和对象和隐含this指针)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++(类和对象和隐含this指针)

目录
  • 1.内和对象
    • 1.面向过程和面向对象初步认识
    • 2.类的引入
    • 3类的访问限定符
    • 4.封装
    • 5.类的作用域
    • 6.类的实例化
    • 7.类的运算
  • 2.隐含的this指针

1.内和对象 1.面向过程和面向对象初步认识

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

2.类的引入

c语言是不是能这样写

struct student
{
	char _name[20];
	char _gender[3];
	int _age;
};

但是c++就不只是这样了,c++把结构体升级引出了一个叫类的概念

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

// C++兼容C struct的用法
// C++同时对struct进行了升级,把struct 升级成了类
// 1、结构体名称可以做类型
// 2、里面可以定义函数
struct student
{
	void Init(const char* name, const char* gender, int age)
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}
	void printf()
	{
		cout << _name << " " << _gender << " " << _age << endl;
	}
	char _name[20];
	char _gender[3];
	int _age;
};

1、结构体名称可以做类型这个怎么理解
比如我们要写个链表的结构体
C语言

struct LisNode
{
	int val;
	struct LisNode* next;
};

C语言不能结构体名称做类型,c++可以
c++

struct LisNode
{
	int val;
	LisNode* next;
};

不过因为c++支持c所以用c的写法也是可以的
2.使用结构里面的函数

#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;

// C++兼容C struct的用法
// C++同时对struct进行了升级,把struct 升级成了类
// 1、结构体名称可以做类型
// 2、里面可以定义函数
struct student
{
	void Init(const char* name, const char* gender, int age)
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}
	void printf()
	{
		cout << _name << " " << _gender << " " << _age << endl;
	}
	//这里不是必须加_
	//是习惯用来表示成员变量
	char _name[20];
	char _gender[3];
	int _age;
};


int main()
{
	student s1;
	s1.Init("zhangsan", "nan",18);
	return 0;
}

这里还有一个问题,c++不是向上找的吗?为什么成员变量不放上面,其实这里成员变量放哪里都可以,只是这是一个类,可以把它看成一个整体

对于上面的代码c++更喜欢用class,而不是struct,就是

class student
{
};

而student s1;这个s1也不叫变量了,改成叫对象了

3类的访问限定符

public限定符代表着它之后的都是公有的

class student
{
public:

	void Init(const char* name, const char* gender, int age)
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}
	void printf()
	{
		cout << _name << " " << _gender << " " << _age << endl;
	}
	//这里不是必须加_
	//是习惯用来表示成员变量
	char _name[20];
	char _gender[3];
	int _age;
};


int main()
{
	student s1;
	s1.Init("zhangsan", "nan",18);
	s1.printf();
	return 0;
}

把public注释了再运行一下


报错了,说无法访问,这是因为class本身就是私有的
换成struct可以编译过,说明struct是共有的
那么能不能在它们下面加访问限定符,答案是可以的
通常都是共有和私有一起用的,因为一串代码里面肯定有不想让人修改的代码
比如这样

class student
{
public:
	void Init(const char* name, const char* gender, int age)
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}
	void printf()
	{
		cout << _name << " " << _gender << " " << _age << endl;
	}
private:
	//这里不是必须加_
	//是习惯用来表示成员变量
	char _name[20];
	char _gender[3];
	int _age;
};

这样子就访问不了成员了,但是里面的函数还可以用
除了共有(public)和私有(private),还有保护(protected),在现阶段它和私有差不多也是类外不能访问

4.封装

讲封装我们先讲讲c语言是怎么样的,C语言数据和方法是分离的
代码,栈的代码,没写全部,只写个架子,主要是为了理解为什么c语言的不好用

 //C -- 数据和方法是分离的
 //太自由
struct Stack
{
	int* _a;
	int _top;
	int _capacity;
};

void StackInit(struct Stack* ps)
{
	ps->_a = NULL;
	ps->_top = 0; // ps->_top = -1;
	ps->_capacity = 0;
}

void StackPush(struct Stack* ps, int x)
{}

int StackTop(struct Stack* ps)
{}

int main()
{
	struct Stack st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);

	printf("%dn", StackTop(&st));
	printf("%dn", st._a[st._top]); // 可能就存在误用
	printf("%dn", st._a[st._top-1]); // 可能就存在误用

	return 0;
}

这里其实就是有的人可能用代码不规范,直接访问top,但是作为这个栈代码,不是你自己写的,那么你那种调用就有可能误用,因为你不知道你栈顶是首位还是首位的后一位
c语言太过自由,约束太少,毕竟不同的人有不同的习惯,所以代码的使用也是因人而异
而c++就用了类,把成员和函数连接在一起,强行让使用代码的人,代码规范化
代码

// 封装:更严格管理设计
// 1、数据和方法封装到一起,类里面
// 2、想给你自由访问的设计成共有,不想给你直接访问的设计成私有
// 一般情况设计类,成员数据都是私有或者保护,想给访问的函数是共有,不想给你访问时私有或保护
class Stack
{
private:
	void Checkcapaicty()
	{}
public:
	void Init()
	{}

	void Push(int x)
	{}

	int Top()
	{}

private:
	int* _a;
	int _top;
	int _capacity;
};

int main()
{
	Stack st;
	st.Init();
	st.Push(1);
	st.Push(2);
	st.Push(3);
	st.Push(4);

	cout << st.Top() << endl;
	//cout << st._a[st._top] << endl;

	return 0;
}

比如这样,让不能用的私有化,能用的公有化,函数的调用也限制掉,比如之前的cout << st._a[st._top] << endl;如果和c语言一样调用的话,编译器会编译不过去

5.类的作用域

代码

class stack
{
public:
	void Init();
};

class Queue
{
public:
	void Init();
};

这二个为什么能同名,这是不是重载,重载是要求同一个作用域,而不同作用类域同名也可以同时存在

c语言一个函数分成一个又一个的文件
那么c++是怎么实现头文件和主函数的
头文件

class Stack
{
public:
	// 在类里面定义
	// 在类里面定义的函数默认是inline
	void Init()
	{
		_a = nullptr;
		_top = 0;
		_capacity = 0;
	}

	// 在类里面声明
	void Push(int x);
	void Pop();
	// 总结一下:实际中,一般情况下,短小函数可以直接在类里面定义,长一点函数声明和定义分离
private:
	int* _a;
	int _top;
	int _capacity;
};

栈函数

#include "Stack.h"

// ʵ
void Stack::Push(int x)
{
	// ...
	_top++;
}

void Stack::Pop()
{

}

这里为什么能访问成员,因为私有限制的是类外的,在类里面是不限制的
,比如房子,房产证的名字是你的,这是不是只属于你私有的房子,那么对于它的主人,你是不是有权限改变先东西,而指定域,Stack:的意思就是进入类域

这里有个问题下面代码是声明还是定义
这个是上面代码截一下部分下来的

//private:
	int* _a;
	int _top;
	int _capacity;

看是声明还是定义,其实就看他有没有开辟空间,没开辟就是声明,开辟了就是定义,所以这个是声明,定义是在Stack st;这串代码里

6.类的实例化

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

  1. 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
  2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
  3. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
7.类的运算
class Stack
{
private:
	void Checkcapaicty()
	{}
public:
	void Init()
	{}

	void Push(int x)
	{}

	int Top()
	{}

private:
	int* _a;
	int _top;
	int _capacity;
};

int main()
{
	Stack st;
	
	cout << sizeof(st) << endl;
	//cout << st._a[st._top] << endl;

	return 0;
}

这里打印的是12,像那些函数没算上去

代码 下面st1和st2一样吗?调用是的同一个函数吗?

int main()
{
	Stack st1;
	st1._top;
	st1.Init();
	Stack st2;
	st2._top;
	st2.Init();
}

从汇编看到是调用的同一函数

但是他们的不一样的,可能st1的top是5,st2的top是10,他们分别在公共代码段里存储着不用的值
代码,求A1打印结果

class A1 {
public:
	void f1() {}
private:
	int _a;
	char _c;
};

int main()
{
	cout << sizeof(A1) << endl;
	return 0;
}

结果

这个简单,int四个字节char一个字节又因为最大对齐数是int所以要求被四整除,所以自动对齐到8

代码 一样 求A2和A3打印结果

class A1 {
public:
	void f1() {}
private:
	int _a;
	char _c;
};

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

class A3
{};

int main()
{
	cout << sizeof(A1) << endl;
	cout << sizeof(A2) << endl;
	cout << sizeof(A3) << endl;
	return 0;
}

结果

为什么会有1字节,这A2和A3这个1不是为了存有效数据而是为了占位置,表示对象存在
但是如果这样的话
代码

class A3
{
	char _c;
};

这样就是用来存有效数据char了

2.隐含的this指针

代码

class Date
{
public:
	void printf()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	void SetDate(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};
int main()
{
	Date d1, d2;
	d1.SetDate(2022, 5, 14);
	d2.SetDate(2022, 5, 13);
	d1.printf();
	d2.printf();
	return 0;
}

根据我们上面得到的这二个调用的是同一个函数,但是它们存的数据不同,分别放在公共代码区,那么它们是用什么区别的?
这里就要讲到this指针了
它们被编译器处理了变成什么样呢?
图片

它们会从图片上部分被编译器处理变成图片下半部分的样子,这样子就可以完全看懂了,它们调用了同一个函数,但是它们传的形参不是相同的

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883824.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号