声明,定义,初始化,实例化

简介: 声明,定义,初始化,实例化


相信很多小伙伴这几个词的概念还没有搞得很懂,今天我来举几个小李子帮助大家深刻理解。有用的话点赞再走哦!

引入:为什么定义变量时要声明和定义分离呢

先来了解变量声明和定义的关系

 为了可以把程序拆成多个逻辑部分来编写,通常支持分离式编译的机制,该机制可以允许我们将程序分割为多个文件,每个文件具有各自的作用,可独立被编译。

下边是实现飞机大战时使用分离式编译的写法,每一个文件执行各自的功能,出错时也方便寻找错误。

 如果将程序分为多个文件,就需要有在文件中共享代码的方法,一个文件的代码中可能需要使用另一个文件中的变量。举一个常见的例子就是C++中std::cout和std::cin,他们定义在标准库中,却能被我们写的程序使用。

为了支持分离式编程,C++将声明和定义分开,声明使该名字被程序所知,一个文件想使用别处定义的名字就必须要包含对哪个名字的声明,定义则是负责创建与名字关联的实体。

也就是声明后,不一定有实体,而定义就是创建实体。

 变量声明规定了变量的类型和名字,定义也规定了变量的类型和名字,但是除此之外,定义还会申请空间,也可能为该变量赋一个初始值。

如果想声明一个变量而不是定义它,就在变量名前加上extern,而不是显式地初始化变量

extern int i; //声明i而不是定义i

int j; //声明并且定义

 但任何包含了显示初始化的声明即成为定义,我们给由extern关键字标记的变量赋上初始值,这么做就抵消了extern的作用。extern语句如果包含初始值就不再是声明而是定义了,因为我们给该变量创建实体以保存其初始化的数值。

说了很多,不如实践演示一波

这里的报错就是未声明标识符。是编译错误。

当我们给extern修饰的变量附上初始值,就会发现可以正常运行。

声明就像是给你一个承诺,但是我可能会忘记实现承诺,从而导致错误。

 你哥们要买房,过来告诉你借点钱,你刚好兜里有点,爽快的答应了,说过一会儿转到他的账上,但是一转眼你忘记了这件事,你哥们首付都交了,又打电话过来问你钱转了吗?怎么没收到,你忽然才想起来,然而你的小积蓄给女朋友买了一个大戒指,已经没有钱了,你和兄弟说完兄弟就崩溃了,答应是全款,这下没钱付,要付违约金,你哥们就崩溃了。这就是因为你定义了,说马上把钱打过去,然而你没打,哥们有钱吗?没有,哥们崩溃了。


声明可以多次声明,你当然可以给多个哥们画大饼,不同的程序都可以得到来自你的声明,他们都觉得事情已经妥了,然而声明过来的变量却没有定义。许多程序(哥们)就崩溃了。

声明可以多次声明,但是定义只能有一次。变量的定义只能出现在一个文件中。

 总结一下就是声明和定义分离,可以使其他想用到该文件中某变量的文件通过声明使用该变量。

函数的声明和定义

我们可以类比变量的声明和定义,其实都一样的。

 还记得在C语言中我们写main函数外的函数都要放在main函数下边,不然就要在前边写一个函数声明吗?(先看现象,后挖掘本质)

举一个很常见的例子

此时程序正常运行

 此时就会报错,找不到Add函数,这是因为程序运行时是从上到下一次执行的,在main函数前边没有发现Add函数,所以会报错,我们要声明一下,告诉编译器我们写了Add函数了的。

 对于第一次运行是可以运行的原因就是,第一次运行时同时进行了声明和定义。

 对于函数,同样可以用extern修饰,但是extern可以省略。

在这里,声明和定义的关系我想你已经烂熟于心了。

类的声明和定义

这里只谈类的声明和定义,深入了解一下?类和对象

类的声明和定义不同于前边。

 我们可以仅仅声明一个类暂时不定义他,这种声明称为前向声明,他在声明之后定义之前是一个不完全类型。

 如果看了前边我所推荐的文章就可以更加理解,对于不完全类型,使用场景十分有限,由于他没有实体,编译器无法知道存储该数据成员需要多少空间,所以类必须先被定义,然后才能引用或使用指针访问其成员。

 类的定义必须要有类名和类体,类体中的变量称为类的属性和成员变量,类中的函数称为类的方法或者成员函数。

类的两种定义方式:

  1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内
    联函数处理。
class Person
{
public:
  void Print()
  {
    cout << "hello" << endl;
  }
  int _age;
  int _grade;
};
  1. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::

初始化的概念

 初始化在计算机编程领域中指为数据对象或变量赋初值的做法,初始化和声明是有明显区别的,变量声明一定是先于初始化进行的,一个包含初始化的声明则通常被称为定义。

 C++定义变量时如果没有给其赋初始值,会根据其位置判断要不要给他默认初始值。默认初始值由该变量的类型来确定。

 如果在任意函数外定义的变量赋值为0,定义在函数内部的内置类型不被初始化,一个没有被初始化的内置类型的值是未定义的,如果试图拷贝或者以其他形式访问该类值将会引发错误。

如图

如果将下边的放开

 在C++中,初始化用=号的方式,很容易让人们认为初始化是赋值的一种,然而初始化和赋值完全是两种不同的操作,人们很容易把二者的区别混为一谈。

 初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象非当前的值擦除,用一个新的值来代替。

一个变量只会初始化一次,再次就是赋值,不然就会重定义。

如果再次初始化就会报错

实例化的概念

 实例化是指在面向对象编程中,用类创建对象的过程,是将一个抽象的概念类,具体到该类实物的过程。

 定义一个类,但是并没有有分配实际的内存空间来存储它。一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量。

 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间。

总结一下:

 实例化是面向对象过程中用类创建出对象的过程,初始化是为创建出的数据对象赋上初值的过程,声明变量或函数时可以理解为一个承诺,告诉编译器有我这个变量或者函数存在,但是真的存在吗?他不一定已经定义过了,在编译时我知道他是存在的,链接时找遍全场都没有找到,程序就崩溃了。声明是告诉你我存在,定义是生成实体。

 本文到这里就结束啦,有用的话留一个赞再走叭,如果你的慧眼金睛发现了问题,一定要说哦,我会虚心改正哒。

目录
相关文章
clion中cpp文件显示This file does not belong to any project ,code insight features might not work【解决方案】
clion中cpp文件显示This file does not belong to any project ,code insight features might not work【解决方案】
clion中cpp文件显示This file does not belong to any project ,code insight features might not work【解决方案】
|
6月前
|
NoSQL Java 测试技术
全链路压测硬核实战:从方案落地、瓶颈根因定位到全链路性能优化
全链路压测是保障微服务系统稳定性的核心手段,通过模拟真实线上流量,在预发或生产环境验证端到端性能与容错能力,精准暴露跨服务调用、资源竞争等隐藏瓶颈,并提供标准化的定位与优化方案。
868 3
|
6月前
|
NoSQL 编译器 Linux
征服黑盒:手把手教你在QNX系统里玩转编译器与调试器
本文深入解析QNX微内核系统原理与开发实践:从“极简稳定”的微内核架构、核心消息传递机制,到交叉编译(qcc)、远程调试(GDB+pdebug)、性能分析(System/Application Profiler)及共享内存等高阶技术,覆盖驱动开发、C++移植、ROS 2集成与实战IPC服务构建,助力嵌入式开发者掌握车规级实时系统开发全栈能力。(239字)
826 9
|
消息中间件 自然语言处理 运维
微服务不是银弹!这4个设计原则让你少踩90%的坑
本文深入解析微服务架构与领域驱动设计(DDD)的核心理念与实践方法,帮助开发者正确拆分服务边界,避免常见误区,提升系统可维护性与扩展性,适用于复杂业务场景下的高效开发与团队协作。
1264 1
静态方法和实例方法的区别是什么?
静态方法和实例方法的区别是什么?
1632 5
|
存储 缓存 网络协议
5个Android性能优化相关的深度面试题
本文涵盖五个Android面试题及其解答,包括优化应用启动速度、内存泄漏的检测与解决、UI渲染性能优化、减少内存抖动和内存溢出、优化网络请求性能。每个问题都提供了详细的解答和示例代码。
710 2
|
JavaScript 前端开发
VUE技术栈-Vue的基本使用
尹正杰在其博客中介绍了Vue.js框架,它是一个渐进式JavaScript框架,由尤雨溪开发,结合了AngularJS的模板语法和数据绑定以及React的组件化和虚拟DOM技术,适合构建高效、轻量化的用户界面。
383 4
|
缓存 NoSQL 关系型数据库
Redis第二课,1.set key value(设置对应的key和value)2.get key(得到value值)Redis全局命令(支持很多的数据结构)3.keys(用来查询当前
Redis第二课,1.set key value(设置对应的key和value)2.get key(得到value值)Redis全局命令(支持很多的数据结构)3.keys(用来查询当前
|
机器学习/深度学习 搜索推荐 PyTorch
【机器学习】图神经网络:深度解析图神经网络的基本构成和原理以及关键技术
【机器学习】图神经网络:深度解析图神经网络的基本构成和原理以及关键技术
4360 3
|
Java Spring
Spring框架: Spring Bean的生命周期是什么样的?
Spring Bean经历实例化、属性赋值、初始化和销毁四个阶段: 1. 反射创建Bean实例。 2. 注入属性值通过setter方法。 3. 执行用户定义的初始化方法(init-method)。 4. 不再需要时,调用销毁方法(destroy-method)。生命周期中,自动操作与用户扩展点并存。
552 0

热门文章

最新文章