目录
一. 类的定义
【对比c】结构体和类的区别
1. 称呼:变量 or 对象?
2. 类型:
3. 访问限定:
4. c和c++结构体使用
5. 相同点:
二. 类域
三. 实例化
1. 1对N
2. 计算大小只考虑成员变量
3. 到此一游
四. this指针
this的隐藏使用
注意:
this作用:
题目深刻理解this
一. 类的定义
< c++中,类可以用class关键词实现,也可以用结构体struct实现 >
以下是class关键词的使用
如下代码, class为定义类的关键字,Stack为你取的类的名字,{ }内为类的主体
class Stack
{
//成员变量
int* array;
size_t capacity;
size_t top;
//成员函数
void Init(int capacity = 4)
{
}
};
注意一:也许会遇上如下初始化的时候,capacity(成员变量) = capacity(函数创建的临时变量)
区分方法:定义成员变量可以在变量前加标识符“_”
class Stack
{
//成员变量
//定义成员变量可以在变量前加标识符“_”
int* _array;//如 int* _array 或者 array_
size_t _capacity;//加标识符是为了方便区分如下函数Init的初始化谁是谁
size_t _top;
//成员函数
void Init(int capacity = 4)
{
//一目了然,左边是成员变量,右边是函数接收传参的临时变量
_capacity = capacity;
}
};
注意二:
【对比c】结构体和类的区别
以下是我们定义数据结构中“栈”用结构体和类两种形式的代码
//定义栈的结构体
typedef int STDataType;
typedef struct Stack
{
STDataType* arr;
int capacity;
int top;
}ST;
//Stack类
class Stack
{
//成员变量
int* array;
size_t capacity;
size_t top;
}
1. 称呼:变量 or 对象?
2. 类型:
- 结构体的类型是 struct Stack(除非你取typedef 类型名称)
- 类的类型直接就是 Stack
3. 访问限定:
扩展知识:c++访问限定符
共有(public) :类外也可以访问(如也可以在main中使用)
私有(private):只允许类内访问
- 结构体默认公有(c++也可以对结构体进行自定义共有和私有)
- 类默认私有(没加访问限定符的时候)
- 类可以自定义 共有(public) 和 私有(private)
4. c和c++结构体使用
c++比c语言多了可以在结构体里写函数 ,且c++的结构体不用typedf也能直接省略struct做类名
5. 相同点:
调用对象/函数 .
调用指针 ->
Stack.Init();
ST.Init();
Stack->arr;
ST->arr;
二. 类域
.c++一共有四大域:函数局部域、全局域、命名空间域和类域。
而我们之前在类中定义的成员函数和成员变量,就属于类域。
通俗说,不同类域相当于不同家族,不同家族里可以都叫“张伟”不会混,相同家族就有可能。
函数 声明定义分离 要 指定类域
声明与定义区分的根本是:是否有开辟空间
- 声明:系统未给开辟空间
- 定义:系统给开辟了空间
头文件定义后,在源文件使用要声明类
格式: 函数返回类型 类名:: 函数名(传参列表)
void Stack:: Init (int n)
举例来说 如下就是标准的类的声明和定义分离
在Stack.cpp文件中指定我们要查找的函数Init(),前面带上指定的类域
Stack.h
复习一下:(缺省参数在声明和定义都在的时候只能给声明,不能给定义)
//这是你头文件定义的类的基本结构
class Stack
{
public:
void Init(int n = 4);//缺省参数在声明和定义都在的时候只能给声明,不能给定义
private:
int* _a;
int top;
int _capacity;
};
Stack.cpp
为了让编译器找到类中的函数,我们需要在前面加上 Stack:: 指定类域
#include"Stack.h"
//我们在类外面定义函数
void Stack::Init(int n )
{
//...
}
三. 实例化
这是我之前写的博客内容
1. 1对N
一个类可以实例化多个对象
2. 计算大小只考虑成员变量
不包含成员函数
计算方式遵循内存对齐原则
3. 到此一游
当类中只有成员函数或者类为空类时,其所创建的对象大小为1字节,纯属占位作用。
四. this指针
this的隐藏使用
代码引入
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass(int a = 0, float b = 0, char c = 0)//构造函数,用于初始化对象的成员变量,后续会给大家介绍
{
_a = a;
_b = b;
_c = c;
}
void Print()
{
cout << _a << endl;
cout << _b << endl;
cout << _c << endl;
}
private:
int _a;
float _b;
char _c;
};
int main()
{
MyClass m = { 1,5.5,'w' };
m.Print();
}
如上print函数没有参数,为什么能准确传参?
实际上,这里的Print函数的参数的第一个位置,存在一个隐含的this指针。
该函数调用当中的this指针指向的是对象m,自动访问其地址
注意:
形参和实参传参列表(this指针会自动在参数第一个位置生成)不可直接使用this,仅可在类的成员函数中使用。
this作用:
1. 当我们需要使成员函数返回该对象的地址,就可以return this;
2. 当函数内的局部变量与类的成员变量名发生冲突时,就可以在类成员前加上this->,便于区分。
题目深刻理解this
1. 以下代码的运行结果是?
#include <iostream>
using namespace std;
class MyClass
{
public:
void Print()
{
cout << "hehe" << endl;
}
private:
int _a;
};
int main()
{
MyClass* a = nullptr;
a->Print();
}
题目简单说,就是创建类指针a,并调用函数Print
答案:正常运行,打印“hehe”。
解析:虽然使用了“->”,但是并没有对空指针a进行解引用,本质是将a传递给了形参this指针。
没有解引用→没有访问成员变量,只打印了“hehe”,所以不会发生问题,程序正常运行。
2. 以下代码的运行结果是?
#include <iostream>
using namespace std;
class MyClass
{
public:
void Print()
{
cout << _a << endl;
}
private:
int _a;
};
int main()
{
MyClass* a = nullptr;
a->Print();
}
答案:运行崩溃。
解析:函数内部访问成员变量_a,_a本质是由this指针解引用访问到的
出现空指针解引用的问题,运行崩溃。
希望对你有帮助