C++的类和对象(一):类的定义 && 初始化 && 访问限定符 &&类实例化

目录

面向对象和面向过程的初步认识

类的引入

类的定义

小拓展 

类的访问限定符及封装

访问限定符

封装 

类的实例化

计算类的大小

定义与初始化

总结


面向对象和面向过程的初步认识

面向过程(C语言):关注过程,分析求解问题的步骤,通过函数调用逐步解决问题

面向对象(C++):关注对象,将一件问题拆分成不同的对象,靠对象之间的交互解决问题

在洗衣服的过程中,总共有四个对象:人、衣服、洗衣粉、洗衣机;

整个洗衣服过程:人将衣服放进洗衣机、倒入洗衣粉、启动洗衣机、洗衣机就会完成洗衣并甩干

        整个过程主要是人、衣服、洗衣粉、洗衣机四个对象之间交互完成的,人不需要关心洗衣机具体是如何洗衣服,如何甩干的

类的引入

基本概念:在C++中,结构体内既可以定义变量也可以定义函数(数据与方法不分离)

typedef int DataType;
struct Stack
{
     //成员变量
     int* a;
     int top;
     int  capacity;

     //成员函数
     void Init(int n = 4)
     {
         a = (int*)malloc(sizeof(int) * n);
         if (nullptr == a)
         {
             perror("malloc申请空间失败");
             return;
         }
         capacity = n;
         top = 0;
     }

     void Push(int x)
     {
         //扩容...
          a[top++] = x;
     }
};

int main()
{
     Stack st2;
     st2.top = 0;
     st2.Init();
     st2.Push(1);
     st2.Push(2);
     st2.Push(3);
     return 0;
}

上面结构体的定义,在C++中更喜欢用class来代替

类的定义

格式:

class classname
{
    类体
};
  • class:定义类的关键字
  • classname:类的名字
  • 类体:类成员的集合,其中的变量称为类的属性或成员变量,函数称为类的方法或成员函数

 类的两种定义方式:(推荐后者)

1、成员的声明和定义全放在类中(成员函数在类中定义,编译器可能会将其当成内联函数处理)

2、 成员的声明放在头文件中,成员的定义放在源文件中(成员函数名前需要加类名::)

        在不加::时,程序在寻找howInfo函数时会以局部域->全局域的顺序寻找,而对于类内部定义的成员函数howInfo(处于类域中的函数)在没有明确指定所属类名时,默认不是为全局可见

注意事项:为应对成员变量与参数名字可能相同的情况,类中的成员变量名前可以加_、m_、m等

class Data
{
    void Init(int yead,int month,int day)
    {
    _year = year; //否则可能就是year = year,分不清形参和成员变量
    _month = month;
    _day = day;
    }
    
    int _year;
    int _month;
    int _day;
}

小拓展 

        类的成员声明和定义分离除了可以提高代码的维护性,还可以优化编译时间,这是因为在大多数情况下,当你构建一个程序时(通过编译和链接),整个项目中的源文件会被重新编译。这意味着即使只修改了一个源文件,也可能需要重新编译整个项目的所有源文件。

        然而,在实际开发过程中,并非每次都需要从头开始完全重新构建整个项目。现代构建系统通常会利用依赖关系来减少不必要的重复工作。

        如果你只修改了某些部分并且没有更改接口(例如类的公共成员函数声明),一些构建工具可以检测到仅受影响部分的更改,并只重新编译相关联的代码。这种方式称为增量构建,它可以节省大量时间,特别是对于大型项目。

        因此,虽然在理论上每次执行程序时都需要将整个项目中所有文件重新编译以生成最终可执行文件或库,但实际上现代开发环境和工具会尽力优化这一过程以提高效率并减少不必要的重复操作。

类的访问限定符及封装

访问限定符

C++提供了三个访问限定符:public(公有)、protected(保护)、private(私有)

  • public:被它修饰的成员可以直接在类外被访问
  • protected和private:它们修饰的成员不可以直接在类外被访问(二者暂时类似)

格式: 

class classname
{
 public:
    {
        成员
    }
   或
 private:
        成员
};

 注意事项:

1、class默认访问权限是private,struct默认访问权限是public(因为它还要兼容C)

2、访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止

3、如果访问限定符后没有括号括起来,那么它的作用域就是直到整个类结束(格式中的private)

4、如果访问限定符后有括号括起来,那么它的作用域就是这个括号(格式中的public)

5、struct中也可以用访问限定符(struct和class的区别除了默认访问权限,就是前者要兼容C,其余一样,所以struct中也可以用访问限定符)

6、类中成员变量的访问权限一般都是私有(会通过公共方法来间接地操作这些私有数据),成员函数的访问权限一般是共有

封装 

面向对象的三大(主要)特性:封装、继承、多态

定义:将数据和操作数据的方法结合,隐藏对象的属性和实现细节仅对外公开接口和对象进行交互

(对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件,对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如 何设计的等,只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以 及键盘插孔等,让用户可以与计算机进行交互即可

封装的本质是一种管控,目的是让用户更方便使用类

实现方式:在C++中,通过类将数据以及操作数据的方法结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用

类的实例化

#include <iostream>
using namespace std;
class Data
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

private:
	int _year;
	int _month;
	int _day;

};

int _year是声明还是定义?

答:int _year是声明

#include <iostream>
using namespace std;
class Data
{
public:
	void Init(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Print()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}

//private:
	int _year;
	int _month;
	int _day;

};

int main()
{

	Data d1;
	Data::_year++; //wrong
	d1._year++;
}

如果我们将int _year的访问权限改为public,那么可以用Data::_year++吗?

答:不,因为_year依然是一个声明,即使在类域找到它,但由于它没有空间还是不能访问它

为什么d1._year++就可以正常使用呢?
答:d1对_year进行了对象实例化,简单来说就是为变量_year开辟了空间

计算类的大小

上面代码中的类的字节大小是多少?

答:是12,依据内存对齐原则,三个整型的成员变量的字节大小就12字节了,而该类中还有Init和Print两个函数,它们所占用的字节数跑哪儿了?

        我们创建两个Data类的对象d1和d2,然后d1和d2分别尝试访问类中的成员变量_year,对此,这两个_year一定是处于两个不同的空间d1 和 d2 是两个不同的对象,它们各自拥有独立的成员变量 _year_month_day,每个类对象都会分配自己的内存空间来存储这些成员变量),但是当d1和d2调用类中的Print函数时,通过汇编指令可以发现,两个函数的地址是一样的,即两个函数所处同一片空间

这是为什么呢?

答: 被同一个类实例化的多个对象,这些对象有两种存储数据的方式

方式一:(既包含成员变量,又包含成员函数)

缺点:用类实例化多个对象,对于不同的对象,它们的变量是不一样的,但是成员函数是一样的(规定)如果按照这种方式存储,每个对象中都会保存一份成员函数的代码,浪费空间

方式二: (只保存成员变量,成员函数存放在公共的代码段)

优点:解决方法空间浪费的问题(厨房每家每户都需要有,但是健身房可以在小区楼下的公共空间建一个大家一起用,总不能一家搞一个健身房)

#include <iostream>
using namespace std;

// 类中既有成员变量,又有成员函数
class A1 {
public:
	void f1() {}
private:
	int _a;
};

// 类中仅有成员函数
class A2 {
public:
	void f2() {}
};
// 类中什么都没有---空类
class A3
{};


int main()
{
	cout << sizeof(A1) << endl;
	cout << sizeof(A2) << endl;
	cout << sizeof(A3) << endl;
	return 0;
}

sizeof(A1)sizeof(A2)sizeof(A3)分别是多少?为什么?

答:4、1、1,因为C++规定没有成员变量大小的类占用一个字节(这一个字节起标识符作的用,不存储有效数据)

定义与初始化

基本概念:定义不是初始化 

注意事项:变量定义的标志是开空间,可以在定义的时候进行初始化,也可以不初始化

int main()
{
    int i = 20;
    int j;
    return 0;
}

总结

  • 类实例化对象:用设计蓝图造房
  • 类:设计蓝图,包含了房子应该有哪些特征和功能
  • 实例化对象:房子

~over~

  • 32
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值