【C++航海王:追寻罗杰的编程之路】类与对象你学会了吗?(上)

慈云数据 2024-03-15 技术支持 139 0

目录

1 -> 面向过程与面向对象的初步认识

2 -> 类的引入

3 -> 类的定义

4 -> 类的访问限定符及封装

4.1 -> 访问限定符

4.2 -> 封装

5 -> 类的作用

6 -> 类的实例化

7 -> 类对象模型

7.1 -> 如何计算类对象的大小

7.2 -> 类对象存储方式的猜测

7.3 -> 结构体内存对齐规则

8 -> this指针

8.1 -> this指针的引出

8.2 -> this指针的特性

8.3 -> C语言和C++实现Stack的对比



1 -> 面向过程与面向对象的初步认识

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

    模拟一个做饭的场景:

    在C语言中,我们可以定义一个主函数,然后按照面向过程的思路,将做饭的各个步骤拆分成不同的函数,每个函数负责一个特定的任务,比如洗菜、切菜、烧火、炒菜等。在主函数中按照顺序调用这些函数来完成整个做饭过程。在这种方式下,我们需要手动管理各个步骤之间的数据传递和调用顺序。

    在C++中,我们可以定义一个名为"Chef"的类,这个类可以包含一些属性和方法,比如"洗菜"、"切菜"、"烧火"、"炒菜"等。每个方法可以用来执行特定的任务,还可以采用封装性,将一些私有属性和方法隐藏起来。我们可以实例化一个"Chef"对象,然后调用对象的方法来完成整个做饭过程。此外,我们还可以使用继承和多态性来扩展做饭的能力,比如可以创建一个"ChineseChef"类来继承"Chef"类,并且扩展了一些中式烹饪的方法。

    2 -> 类的引入

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

    比如实现栈:

    #include 
    using namespace std;
    typedef int DataType;
    struct Stack
    {
    	void Init(size_t capacity)
    	{
    		_array = (DataType*)malloc(sizeof(DataType) * capacity);
    		if (nullptr == _array)
    		{
    			perror("malloc申请空间失败");
    			return;
    		}
    		_capacity = capacity;
    		_size = 0;
    	}
    	void Push(const DataType& data)
    	{
    		// 扩容
    		_array[_size] = data;
    		++_size;
    	}
    	DataType Top()
    	{
    		return _array[_size - 1];
    	}
    	void Destroy()
    	{
    		if (_array)
    		{
    			free(_array);
    			_array = nullptr;
    			_capacity = 0;
    			_size = 0;
    		}
    	}
    	DataType* _array;
    	size_t _capacity;
    	size_t _size;
    };
    int main()
    {
    	Stack s;
    	s.Init(10);
    	s.Push(1);
    	s.Push(2);
    	s.Push(3);
    	cout 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语言实现时,Stack相关操作函数有以下共性:

    • 每个函数的第一个参数都是Stack*;
    • 函数中必须要对第一个参数检测,因为该参数可能会为NULL;
    • 函数中都是通过Stack*参数操作栈的;
    • 调用时必须传递Stack结构体变量的地址。 结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即数据和操作数据 的方式是分离开的,而且实现上相当复杂一点,涉及到大量指针操作,稍不注意可能就会出 错。

      C++实现:

      #include 
      using namespace std;
      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;
      }
      C++中通过类可以将数据 以及 操作数据的方法进行完美结合,通过访问权限可以控制那些方法在 类外可以被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。 而且每个方法不需要传递Stack*的参数了,编译器编译之后该参数会自动还原,即C++中 Stack * 参数是编译器维护的,C语言中需用用户自己维护。

      感谢大佬们的支持!!!互三啦

微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon