【C++】类和对象(类的定义,类域,实例化,this指针)
目录
一. 类的定义
【对比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指针解引用访问到的
出现空指针解引用的问题,运行崩溃。
希望对你有帮助