0
点赞
收藏
分享

微信扫一扫

Navicat 技术指引 | 适用于 GaussDB 的数据迁移工具

李雨喵 2023-11-26 阅读 53
c++

前言

上一期我们介绍了一些C++入门的基础知识,本期我们来介绍面向对象。初步认识一下面向对象和面向过程、类、以及封装!

本期内容介绍

一、面向过程和面向对象

以前我也不怎么理解面向对象和面向过程!后来看到了很多例子后逐渐有了理解!我来举一个我以前理解最好的例子 --- 洗衣服。

当然还有其他同类的例子,例如把大象装到冰箱里面!

二、类的引入

C语言版本:

typedef int STDataType;
struct Stack
{
	STDataType* a;
	int top;
	int capacity;
};

他的方法只能在外面!而C++就可以在里面!

C++版本:

#include <iostream>

typedef int STDataType;
struct Stack
{
	STDataType* _a;
	int _top;
	int _capacity;

	void Init(int capacity = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * capacity);
		if (_a == nullptr)
		{
			perror("malloc failed");
			exit(-1);
		}

		_capacity = capacity;
		_top = 0;
	}

	//...
};

上述操作可以,但C++中更喜欢用class来替代struct

三、类的定义

class ClassName
{
	//成员变量和成员方法(函数)
};//注意封号

类的两种定义方式

class Student
{
public:
	//成员方法
	void sleep()
	{
		cout << _name << "正在sleep()..." << endl;
	}

private:
	//成员属性
	char* _name;
	char* _sex;
	int _age;
};

当然这里用struct也可以定义类!

成员变量的命名规则

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

访问限定符

访问限定符的说明

OK, 举个栗子看看:

public(在类外可以访问,以属性举例,方法同理):

class Stack
{
public:
	void Init(int capacity = 3)
	{
		_a = (int*)malloc(sizeof(int) * capacity);
		if (_a == nullptr)
		{
			perror("malloc failed");
			exit(-1);
		}

		_size = 0;
		_capacity = capacity;
	}

	void Push(int x)
	{
		//...
	}

	int* _a;
	int _size;
	int _capacity;
};

int main()
{
	Stack s;
	s.Init();
	cout << s._size << endl;

	return 0;
}

这里把class直接换成struct也可以!

private/protectedd当前认为是一样的,在类外不可访问:

C++中struct和class的区别是什么?

注意:在C++中如果用struct定义结构体的话,在结构体类在申明结构体变量时,不用在+struct了

struct SLNode
{
	int* data;
	SLNode* next;
};

封装

五、类的作用域

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

	void Print();

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

//这里注意要指定Print属于Date这个类
void Date::Print()
{
	cout << "999" << endl;
}

六、类的实例化

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

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

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

int main()
{
	Date d;//实例化一个对象
	d.Init(2023, 11, 25);
	d.Print();

	return 0;
}

1、类是描述对象的,是一个模型(模板),它限制了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储他。例如:开学时填写的学生信息表,这个表可以看成一个学生类,他来描述具体的学生(对象)!

2、一个类可以实例化多个对象,实例化出来的对象占用实际的物理空间,存储类成员变量

七、类对象模型

上面我们已经清楚了类的定义以及其实例化对象。一个对象有成员属性也有成员的方法,而我们想知道的是一个对象包含了什么?

OK,关于这个问题我就直接先说结论,再解释了:

我用一个我家鸽鸽的例子来说明:我家鸽鸽属于人这个类,他的名字和性别等是他个人独属于的!他的成员方法(行为)有:唱、条、rap、打篮球。但只有我家鸽鸽会唱、条、rap、打篮球吗?你是不是也可以啊,所以类的成员方法属于类!

class People
{
public:
	//方法属于整个类
	void Sing()
	{
		cout << "鸡你太美~..." << endl;
	}

private:
	//属性属于对象本身
	char _name[20];
	char _sex[5];
	int age;
};

如何计算一个类的大小?

//既有成员变量又有成员方法的类
class A
{
public:
	void Print()
	{
		//...
	}

private:
	int a;
};

//只有成员方法没有成员变量的类
class B
{
public:
	void Print()
	{
		//...
	}
};

//既没有成员变量有没有成员方法的类(空类)
class C
{

};


int main()
{
	cout << sizeof(A) << endl;
	cout << sizeof(B) << endl;
	cout << sizeof(C) << endl;
	return 0;
}

结构体内存对齐规则(和C语言的一样)

如果这块还有问题,请点击后面的链接,这篇博文中我详细介绍过它的计算和栗子:

内存对齐

八、this指针

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(2023, 11, 25);
	d1.Print();

	Date d2;
	d2.Init(2023, 11, 26);
	d2.Print();

	return 0;
}

Init和Print是类的成员方法,我们并没有指定是哪个对象的,为什么我们在调d1.Init的时候就是给d1对象赋值而不是给d2初始化呢?我们在d2.Print的时候是打印d2的属性的信息,为什么不打印d1会随机值呢????他到底是如何区别的呢?

this指针的特性

这应该是这里很坑的两个问题了,对基础考察很细!OK,我还是先说结论,再用栗子来解释!

OK,两个栗子分别解释一下:

栗子1:下列程序的编译运行的结果是?A、编译报错  B、运行奔溃  C、正常运行

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

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

OK,他是C、正常运行!我们来看一下:

栗子2:下列程序的编译运行的结果是?A、编译报错  B、运行奔溃  C、正常运行


class A
{
public:
	void PrintA()
   {
		cout << _a << endl;
   }
private:
 int _a;
};

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

OK,这里是B、运行崩溃!

C语言和C++实现栈的对比

C语言

#include <assert.h>
typedef int DataType;
typedef struct Stack
{
	DataType* array;
	int capacity;
	int size;
}Stack;


void StackInit(Stack* ps)
{
	assert(ps);
	ps->array = (DataType*)malloc(sizeof(DataType) * 3);
	if (NULL == ps->array)
	{
		assert(0);
		return;
	}

	ps->capacity = 3;
	ps->size = 0;
}

void StackDestroy(Stack* ps)
{
	assert(ps);
	if (ps->array)
	{
		free(ps->array);
		ps->array = NULL;
		ps->capacity = 0;
		ps->size = 0;
	}
}

void CheckCapacity(Stack* ps)
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity * 2;
		DataType* temp = (DataType*)realloc(ps->array,
			newcapacity * sizeof(DataType));
		if (temp == NULL)
		{
			perror("realloc申请空间失败!!!");
			return;
		}

		ps->array = temp;
		ps->capacity = newcapacity;
	}
}

void StackPush(Stack* ps, DataType data)
{
	assert(ps);
	CheckCapacity(ps);
	ps->array[ps->size] = data;
	ps->size++;
}

int StackEmpty(Stack* ps)
{
	assert(ps);
	return 0 == ps->size;
}

void StackPop(Stack* ps)
{
	if (StackEmpty(ps))
		return;
	ps->size--;
}

DataType StackTop(Stack* ps)
{
	assert(!StackEmpty(ps));
	return ps->array[ps->size - 1];

}

int StackSize(Stack* ps)
{
	assert(ps);
	return ps->size;
}

int main()
{
	Stack s;
	StackInit(&s);
	StackPush(&s, 1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	StackPush(&s, 4);
	printf("%d\n", StackTop(&s));
	printf("%d\n", StackSize(&s));
	StackPop(&s);
	StackPop(&s);
	printf("%d\n", StackTop(&s));
	printf("%d\n", StackSize(&s));
	StackDestroy(&s);
	return 0;
}

C++:

typedef int DataType;
class Stack
{
public:
	void Init()
	{
		_array = (DataType*)malloc(sizeof(DataType) * 3);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}

		_capacity = 3;
		_size = 0;
	}

	void Push(DataType data)
	{
		CheckCapacity();
		_array[_size] = data;
		_size++;
	}

	void Pop()
	{
		if (Empty())
			return;
		_size--;
	}

	DataType Top() 
	{ 
		return _array[_size - 1]; 
	}

	int Empty() 
	{ 
		return 0 == _size; 
	}

	int Size() 
	{ 
		return _size; 
	}

	void Destroy()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}

private:
	void CheckCapacity()
	{
		if (_size == _capacity)
		{
			int newcapacity = _capacity * 2;
			DataType* temp = (DataType*)realloc(_array, newcapacity *
				sizeof(DataType));
			if (temp == NULL)
			{
				perror("realloc申请空间失败!!!");
				return;
			}
			_array = temp;
			_capacity = newcapacity;
		}
	}

private:
	DataType* _array;
	int _capacity;
	int _size;
};

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

	printf("%d\n", s.Top());
	printf("%d\n", s.Size());
	s.Pop();
	s.Pop();
	printf("%d\n", s.Top());
	printf("%d\n", s.Size());
	s.Destroy();
	return 0;
}
举报

相关推荐

0 条评论