各位好友,欢迎来到本期博客 !今天,正式向 类~~对象 宣战 !接下来,或许很长一段时间,都将接触到大量的

类 对象 !或许是贯穿整个 C++  很早之前,最先接触的语言是 Java 那时 就已经对 类 对象 产生了不一样的情愫!

后来选择方向上,由于引入了 考研所需 这一参数,亦然选择了 C++ 😊希望,本人的选择并不会感到后悔 !

C++ 将会是本人一生打磨的事业 !本人已在心中决定了这个想法 !!

下面开始讲述,类  对象

-----> 类

经过 C 语言的学习,可以得知 :>

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

比如:在前几期的数据结构讲解中,用 C 语言实现栈,结构体中只能定义变量;现以 C++ 方式实现,会发现结构体内可以定义函数 !

如下 :>

文件 “stack.cpp”

#include <iostream>
//using std::cout;
//using std:: endl;

//using namespace std; 	// 不推荐项目中用这种写法,至于原因,前期博文中有讲解

#include <stdlib.h>
#include <stdbool.h>

typedef int STDataType;

// C++ 中结构体类型升级成了 类
// C++ 兼容 C语言, 以前 数据结构的写法仍然可以实现
struct Stack
{
	STDataType* a;
  int capacity;
  int top;
  
  //结构体内可以定义函数
  // 初始化栈区
  void Init(int DefaultCapacity = 4)		// C++ 优化点,自动补全一些参数,这是很香的
  {
  	a = (STDataType*)malloc(sizeof(STDataType) * DefaultCapacity);
    if(a == nullptr)	//空指针 于 C++ 中规范化用法
    {
    		perror("maloc::fail");
      	return ;
    }
    
    capcity = DefaultCapacity;
    int top = 0;
  }
  
  // 销毁栈区
  void Destroy()
  {
  	free(a);
    
    a = nullptr;	// C++ 空指针规范写法
    top = 0;
    capacity = 0;
  }
  
  // 入栈区元素
  void Push(STDataType x)
  {
  	if(top == capacity)
    {
    	STDataType* tamp = (STDataType*)realloc(a, sizeof(STDataType) * capacity * 2);
      if(tamp == nullptr)
      {
	      	perror("realloc::fail");
        	return ;
      }
      
      a = tamp;
      capacity *= 2;
    }
    
    a[top++] = x;
  }
  
  // 减少栈区内元素个数
  void Pop()
  {
    top--;
  }
  
  // 出栈区栈顶元素
  STDataType Top()
  {
    return a[top - 1];  // 若部分好友,对此处不理解,可以参考前几期栈区的讲解
  }
  
  // 布尔判空
  bool Empty()
  {
    return top == 0;
  }
  
}; // 分号别忘记了


int main()
{
  // 第一种写法:
	//struct Stack st1;
  //st1.Init();
  
  // 第二种写法:
  Stack st2;
  st2.Init();
  
  st2.Push(21);
  st2.Push(24);
  st2.Push(27);
  st2.Push(23);
  st2.Push(21);
  
  while(!st2.Empty())
  {
  	printf("%d ", st2.Top());
    st2.Pop();
  }
  
  printf("\n");
  st2.Destroy();
  return 0;
}

-----> 以下展现彩色图样:

为了好友们,有更好的观感体验,特附上彩色代码图样 :>

运行结果 :>

C++ ----> 类 ~~ 对象_01_两种栈区实现方式

实现环节 “Stack.cpp”

C++ ----> 类 ~~ 对象_01_类 对象 入门环节_02

在 C++ 中,显然结构体内可以支持 定义函数体 !其实,用 C++ 实现一个栈区,还是蛮香的 !

虽然 底层逻辑一样,但是 代码更简洁 !

以上代码,函数体中,默认参数可以省略不写,这也是 C++ 运用结构体的一大优势 !

以上实现,运用了 升级版的结构体来实现栈区 ! 其实, 这仍然缺少 C++ 味道 !上述代码,结构体可以用 class 来替代 !

下面来看,具有 C++ 纯正味道的栈区实现 !

头文件 “Stack.h”

#include <iostream>
// using namespace std;
using std :: cout;
using std :: endl;

#include <stdlib.h>
#include <stdbool.h>

// 类域
// 定义类名 Stack
class Stack
{
	// 成员函数
  void Init(DefaultCapacity = 4);  // 此处可以对参数进行赋值,在定义函数体中则不能,否则会出现重定义
  
  void Push(int x);
  
  void Pop();
  
  int Top();
  
  bool Empty();
  
  void Destroy();
  
  // 成员变量
  int capacity;
  int top;
}; // 分号别忘记了

实现文件 “Stack.cpp”

#include "Stack.h"

// 相较于放在一个构体内实现栈区,此处需要特别指明,正在定义的函数来自那个类名
void Stack :: Init(int DefaultCapacity)		// 此处要注意,别重定义了,意即 赋值
{
	a = (int*)malloc(sizeof(int) * DefaultCapacity);
  if(a == nullptr)
  {
  	perror("maloc::fail");
    return ;
  }
  
  capacity = DefaultCapacity;
  top = 0;
}

void Stack :: Push(int x)
{
	if(top == capacity)
  {
  	int* tamp = (int*)realloc(a, sizeof(int) * capacity * 2);
    if(tamp == nullptr)
    {
    	perror("realloc::fail");
      return ;
    }
    
    a = tamp;
    capacity *= 2;
  }
  
  a[top++] = x;
}

void Stack :: Pop()
{
	top--;
}

int Top()
{
	return a[top - 1];
}

bool Empty()
{
	return top == 0;
}

void Destroy()
{
	free(a);
  
  a = nullptr;
  
  top = capacity = 0;
}

int main()
{
  Stack st2;
  st2.Init();		// 此处可以传参数,也可以不传参数; 不传参数,使用默认值 在前几期博文中,有讲解 -->函数的重载
  
  st2.Push(21);
  st2.Push(24);
  st2.Push(27);
  st2.Push(23);
  st2.Push(21);
  
  while(!st2.Empty())
  {
  	printf("%d ", st2.top());
    st2.Pop();
  }		// 其实这么写,太香了
  
  printf("\n");
  st2.Destroy();
	return 0;
}

上述代码,便具有了  C++ 味道 !其实,上述栈区的实现,最大的不同 是 “class” 的引入 !

为了好友们,有更好的观感体验,特附上彩色代码图样 :>

头文件 “Stack.h”

C++ ----> 类 ~~ 对象_01_类 对象 入门环节_03


实现文件 “Stack.cpp”

C++ ----> 类 ~~ 对象_01_代码素养_04

现对以上代码进行部分解析 :>

在头文件 “Stack.h” 中,显然是用了 “class” 来替代 “struct” ! 致使,本章节的主打点来了 !

那么 “class” 究竟是什么呢 ?

-----> class 为定义 类的关键字, “ { } ” 范围内 为类的主体,而“类名”是紧跟 class 后面的名字;注意类定义结束后有一个分号不可以省略 !

类的主体内是类的成员 a. 类中的变量称为类的属性 或成员变量; b. 类中的函数称为类的方法 或成员函数

而类有两种定义:

1.声明和定义全部放在类的主体内,此时,成员函数会被编译器当成 内联函数 进行编译 !

2.类声明放在头文件中,成员函数定义 放在 .cpp 文件中 ;且注意:成员函数 类型之后 需要加上类名 !---> 如下:

C++ ----> 类 ~~ 对象_01_两种栈区实现方式_05

请看上述图示的标注,一定别忘记了,类名的加入,以及类名之后的 “ :: ” 域作用限定符

其实,  也是 一个域,只不过叫做 类域

以上两种定义,推荐大家使用第二种 !并不是因为 第一种有内联函数,而是第二种有着熟悉的感觉 !

前几期,数据结构章节 !实现栈区,队列,二叉树等等 !全部都是多文件实现,而且必须有一个头文件用来声明,之后在实现文件“ xxx.c ” 中进行定义 !如此可见,分开写,多文件并行的情况下,代码量更为可观 !也更容易方便快速查找代码,以及管理和维护代码模块区 !

下面再提及一下,变量名命名的素养与规范 !请看下列图示 :>

(1)不规范,代码可读性差劲的命名样例 :>

C++ ----> 类 ~~ 对象_01_两种栈区实现方式_06

(2)漂亮,值得称赞,美观的代码命名样例 :>

C++ ----> 类 ~~ 对象_01_类 对象 入门环节_07


朋友们,感谢阅读本期博文 !

下一期,为大家带来 访问限定符 “ public ” 讲解,以及继续推进 大类 大对象 😊