C++类和对象介绍(筑基上篇)

目录

1.面向过程和面向对象

2.  类的定义

2.1 struct 定义类

2.2 class定义类

3.类的访问限定符及封装

4. 类的作用域

5. 类的实例化

6.类对象模型

7. this指针

7.1 this 指针的特性


1.面向过程和面向对象

C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用解决问题。

C++是基于面向对象的,关注的是对象,将一件事分成不同的对象,靠对象的交互完成任务。

我们可以简单理解为这些对象,C++ 习惯存放在 类中 ,也就是类域中。 

2.  类的定义

2.1 struct 定义类


struct structname
{
	// 类体   ,包括成员变量和成员函数

}; //不要忘记分号

struct 为C++ 定义类的关键字 ,structname 是我们为这个类 起的名字。

由于C++ 是支持C语言的,因此 ,在C++中 ,我们可以使用struct 来定义结构体,并且正常使用。在C语言中 我们定义的结构体,其内容只有成员变量,但是在C++中,我们可以在类中定义成员函数,这是C语言办不到的。

2.2 class定义类


class classname
{
	// 类体   ,包括成员变量和成员函数

}; //不要忘记分号

C++中更推荐使用 class 来定义类,class为定义类的关键字,classname为类名,{} 中为类的主体。同样,class定义的类,包括成员变量(也可以称为类的属性)和成员函数(也可以称类的方法

那么class 和 struct 同样都可以用来定义类 ,那么它们有没有什么不同?

3.类的访问限定符及封装

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅公开接口来和对象进行交互。封装的本质更像是管理

C++实现封装的方式: 用类将对象的属性和方法结合在一起,让对象更加完善,通过访问权限选择性的将接口提供给外部的用户使用。

简单的来说,给我们定义的类 ,上了很多把锁,只有拿到对应的钥匙,才能访问相应的内容,

或者,在我们定义类的时候,提前把我们希望提供给外部的接口上的锁打开。

访问限定符:

1. public (公有)

2.protected (保护)

3. private (私有)

public 修饰的类的成员 可以在类外直接被访问。

protected 和 private 修饰的成员在类外 不可以直接被访问。

访问权限作用域从该访问限定符出现的位置 到下一个访问限定符出现为止。

class 的默认访问权限为 private ,struct 默认访问权限为 public (因为它需要兼容C)

我们需要注意的是 ,访问限定符只有在编译的时候有用,当数据映射到内存时,没有任何访问限定符上的区别。


class classname
{
public:
	void test1()
	{
		cout << "test1" << endl;
	}
private:
	int a = 10;
	int b = 20;
}; 

例如我们现在定义的类,它的test1函数,可以在类外面被直接调用,但是 a , b 就不可以直接被调用。

4. 类的作用域

类定义了一个新的作用域,类中的成员都在类的作用域中。如果在类体外定义成员,需要用到作用域解析符 ::  (两个英文的冒号),用来指明成员属于哪个类域。

这里顺带说明一下类的两种定义方式:

1.声明和定义全部放在类中,需要注意的是,成员函数在类中定义,编译器可能会把它当做内联函数来处理。不过这取决于具体的情况。

class classname
{
public:
	void test1()   // 声明
	{
		cout << "test1" << endl;   / 定义
	}
private:
	int a = 10;
	int b = 20;
}; 

2. 声明放在.h文件中 , 类的定义放在.cpp 文件中。

.h

class classname
{
public:
	void test1()   // 声明

private:
	int a = 10;
	int b = 20;
}; 

.cpp

#include"test.h"

void classname :: test1()
{
   //  具体实现
}

这里我们就用到了 作用域解析符 ::  

我们定义类时,更推荐第二种。

5. 类的实例化

用类类型创建对的过程就叫类的实例化。

类本身更像一个模型,它限定了类中有哪些成员,定义出一个类,并没有分配实际的内存空间来存储它

一个类可以实例化出多个对象。它实例化的对象,占用实际的物理空间,存储类成员变量。

6.类对象模型

我们知道类中,即可以有成员变量,有存在成员函数,那么一个对象中到底包含了什么,如何计算类的大小?

直接说结论

类中只保存成员变量,成员函数存放在公共代码段。

为什么成员函数和成员变量不一样?如果每个对象都保存一份代码,相同的代码保存多次,浪费空间。每个成员变量是不同的,所以它们保存在对象中。

那么一个类的大小,就是该中成员变量和,和C语言中的结构体内存大小的计算规则相同,需要考虑内存对齐。下面是具体的结构体内存大小计算的博客链接。

(35条消息) 结构体内存大小计算,位段分析_杨斯文。的博客-CSDN博客

但是C++中,我们需要注意空类的大小,空类比较特殊,即类中没有成员变量。空类的大小不是0,而是一个字节,因为编译器给了空类一个字节来唯一标识这个类。

7. this指针

需要我们用一个例子来说明


class Date
{
public:
    void display()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
    void SetDate(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = _month;

    }
private:
    int _year;
    int _month;
    int _day;


};



int main()
{
    Date d1, d2;   // 创建两个类对象
    d1.SetDate(2019, 9, 10);
    d2.SetDate(2022, 9, 18);
    d1.display();
    d2.display();

}

我们创建两个类对象,在我们给对象赋值时,调用了处于公共代码段的成员函数。那么问题来了,直接调用相同的成员函数,那么函数是给d1还是给d2运行,还是说成员函数有方法识别这两个不同的对象。我们来运行一下这个代码。

 我们可以看到,成员函数正确的操作了两个不同的类对象。包括打印函数也是。

但是这不符合正常的逻辑。按道理,这个函数并不能区分出两个不同的类对象。

这里就不得不提出 this指针了。

C++编译器给每个“非静态的成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所以成员变量的操作,都是通过该指针去访问。

只不过这个操作,对用户来说是透明的,不需要用户来实现,编译器自动完成。

7.1 this 指针的特性

1. this 指针的类型 : 类类型 * const    ( const 的作用是 ,保证 this 这个指针不可以改变 )

2. 只能在成员函数内使用。

3.this 指针本质是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参。所以对象中是不存储 this 指针 。 

4. this指针是成员函数第一个隐含的指针形参,一般情况有编译器通过ecx 寄存器自动传递,不需要用户传递。

那么上述代码的运行结果就可以解释了

 除此以外this 指针还有几个我们需要注意的点。

this 指针的存储位置 , 一般情况是在栈(形参),有些编译器会放在寄存器中。

this 可以为空吗?


class Date
{
public:
    void display()
    {
        cout << _year << "-" << _month << "-" << _day <<"test"<< endl;
    }
    void SetDate(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = _month;

    }
    void show()
    {
        cout << "shou" << endl;
    }
private:
    int _year;
    int _month;
    int _day;


};


int main()
{
    Date* p = nullptr;
    p->show();
}

此时p为空 ,我们运行程序。

 程序正常运行。



int main()
{
    Date* p = nullptr;
    p->display();
}

当我们运行打印函数时,会发现

 函数没有崩,但是也并没打印出我们相要的。

我们开辟一个空的类的对象时,传给this的是空,也就是实参是空 ,此时this 作为形参接收了一个空,成为空指针。直到这一步,都是没有错误的。

这也是为什么,我们可以正常使用 show 函数,

但是当我们调用的函数会对this 这个空指针进行解引用时 ,属于对空指针进行操作。这是不对的。所以打印函数没有运行。按道理程序是应该报错的。 

所以this 是空指针是没有问题的 ,但是我们在使用时,需要注意,避免使用野指针。

本篇博客到此结束,谢谢观看。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值