c++--类(上)

简介: c++--类(上)

C++之类(上)
一、类的定义
1.1 类定义格式
1.2 访问限定符
1.3 类域
二、实例化
2.1 实例化的概念
2.2 对象大小
三、this指针
一、类的定义
1.1 类定义格式
1、class为定义类的关键字,{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量; 类中的函数称为类的⽅法或者成员函数。

class stack
{
int*arr;
int size;
int capacity;//成员变量

void Push(int x);
int Top();
void Pop();//成员函数

};
1
2
3
4
5
6
7
8
9
10
这个就是一个栈的类,它与结构体不同,类是变量与函数不分离。

2、为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前⾯或者后⾯加_ 或者 m开头。

class direction
{
public:
void Init(int left, int right, int up, int down)
{
_left = left;
_right = right;
_up = up;
down = down;
}
private:
//在这里有两种方式可以用来区分
//1、在成员变量前加

//2、用this指针例如(this->left=left)
int _left;
int _right;
int _up;
int _down;
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
3、 C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是struct中可以定义函数, ⼀般情况下我们还是推荐⽤class定义类。

struct stack
{
int*arr;
int size;
int capacity;//成员变量

void Push(int x);
int Top();
void Pop();//成员函数

};
1
2
3
4
5
6
7
8
9
10
这个也是可以的。

4、定义在类⾯的成员函数默认为inline。如果我们不想在类里写我们的函数体,就得用::域作用限定符。

class direction
{
public:
void Init(int left, int right, int up, int down);
private:
//在这里有两种方式可以用来区分
//1、在成员变量前加_
//2、用this指针例如(this->left=left)
int _left;
int _right;
int _up;
int _down;
};
void direction::Init(int left, int right, int up, int down)
{
_left = left;
_right = right;
_up = up;
_down = down;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1.2 访问限定符

1、C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的⽤户使⽤。这里的接口指的就是函数。

2、public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是⼀样的,在继承章节才会体现它俩的不同。

大家可以看到size可以轻易的访问,而Top就不能被访问。

3、访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到 }即类结束。

class stack
{
public:
int*arr;
int size;
int capacity;//成员变量
//public的范围到private之前
private:
void Push(int x);
int Top();
void Pop();//成员函数
//后面已经没有访问限定符了,那么private的范围到“}”之前
};
1
2
3
4
5
6
7
8
9
10
11
12
13
4、class定义成员没有被访问限定符修饰时默认为private,struct默认为public。

5、最后访问限定符可以多次出现,但实际使用一般不这样写。

1.3 类域
类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。

特别是这种两个类成员函数名字一样的,一定要指明类域。

二、实例化
2.1 实例化的概念
1、⽤类类型在物理内存中创建对象的过程,称为类实例化出对象。

class direction
{
public:
void Init(int left, int right, int up, int down);
private:
//在这里有两种方式可以用来区分
//1、在成员变量前加_
//2、用this指针例如(this->left=left)
int _left;
int _right;
int _up;
int _down;
};
void direction::Init(int left, int right, int up, int down)
{
_left = left;
_right = right;
_up = up;
_down = down;
}
int main()
{
direction d1, d2;
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
在这里我们就实例化了两个对象d1,d2。

2、类是对象进⾏⼀种抽象描述,是⼀个模型⼀样的东西,限定了类有哪些成员变量,这些成员变量只是声明,没有分配空间,⽤类实例化出对象时,才会分配空间。
什么意思呢?就是我们定义的类只是一个声明,当我们创建对象,例如上面的d1,d2时才会分配空间。

3、⼀个类可以实例化出多个对象,实例化出的对象 占⽤实际的物理空间,存储类成员变量。

2.2 对象大小
类实例化出的每个对象,都有独⽴的数据空间,所以对象中肯定包含成员变量,那么成员函数是否包含呢?⾸先函数被编译后是⼀段指令,对象中没办法存储,这些指令存储在⼀个单独的区域(代码段),那么对象中⾮要存储的话,只能是成员函数的指针。
我们只需要记住在算对象大小的时候,不需要计算成员函数,只计算成员变量。
那现在问题来了,要是我们的类里什么都没有,但我们用它实例化了对象,那实例化后的对象的大小是多少啊?

这⾥给1字节,纯粹是为了占位标识对象存在。

其次我们要算对象的大小我们只需要计算成员变量的大小,其算法与struct的算法一致都是符合内存对齐原则:

那大家有没有想过为什么要内存对齐啊?

三、this指针
首先我们先看一个代码:

class direction
{
public:
void Init(int up, int down, int left, int right)
{
_left = left;
_right = right;
_up = up;
_down = down;
}
public:
int _left;
int _right;
int _up;
int _down;
};
int main()
{
direction d1, d2;
d1.Init(0, 1, 2, 3);
d2.Init(3, 2, 1, 0);
cout << d1._up << ' ' << d1._down << ' ' << d1._left << ' ' << d1._right << endl;
cout << d2._up << ' ' << d2._down << ' ' << d2._left << ' ' << d2._right << endl;
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
为什么这里是同一个函数,打印的确实一样的呢?这里就引入了this指针,this指针通常都是隐含的。

那我们将它恢复回原来的样子:

class direction
{
public:
//void Init(dataconst this,int up,int down......)
void Init(int up, int down, int left, int right)
{
this->_left = left;
this->_right = right;
this->_up = up;
this->_down = down;
}
public:
int _left;
int _right;
int _up;
int _down;
};
int main()
{
direction d1, d2;
d1.Init(0, 1, 2, 3);
//d1.Init(&d1, 0, 1, 2, 3);
d2.Init(3, 2, 1, 0);//d2.Init(data
const this,3,2,1,0);
//d2.Init(&d2, 3, 2, 1, 0);
cout << d1._up << ' ' << d1._down << ' ' << d1._left << ' ' << d1._right << endl;
cout << d2._up << ' ' << d2._down << ' ' << d2._left << ' ' << d2._right << endl;
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
需要注意的是:C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显⽰使⽤this指针。

最后我们需要知道this指针存在于哪个区域,是堆、栈,还是常量区还是对象里?

我们要知道this指针是作为形参传递的对不对,形参存储于栈里,所以在这里栈比较合适,但是由于c++里经常使用this指针,所以有些编译器会将其放入寄存器,但是在做题过程中我们选栈。

这两个题目有助于我们理解this指针,大家可以简单的看下

1、问它运行结果是什么?

include

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

int main()
{
A* p = nullptr;
p->Print();
return 0;
}
//A、编译报错 B、运⾏崩溃 C、正常运⾏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
这个题目选择正常运行,虽然这里p是空指针,但我们这里是将它的地址作为参数传递,成员函数不存于类的变量中,我们访问成员函数并没有通过this指针。

include

using namespace std;
class A
{
public:
void Print()
{
cout << "A::Print()" << endl;
cout << _a << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}//A、编译报错 B、运⾏崩溃 C、正常运⾏

相关文章
|
1天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
13 2
|
7天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
30 5
|
13天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
42 4
|
14天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
40 4
|
1月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
28 4
|
1月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
25 4
|
1月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
22 1
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
1月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)
|
1月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
54 1