C++基础语法:浅析“数据“以及数据作用域

前言

        程序由数据和逻辑两部分组成.数据有两个层面上的含义:程序员角度他是一种客观存在的事物,比如屏幕上看见的一个点,一个图标,或者看不见的比如地址,函数,类等等.在硬件的角度,数据是寄存器或者寄存器的组合."数据"是一种"静态"的存在.而"逻辑"(或者需求,或者函数)需要通过数据的变化来展现.

数据的表示

        从几个层面来看数据的表示

 

数据最重要的两个属性是地址和数据类型.变量和值相对没那么重要(当程序运行后传入的值可能会对程序运行结果产生影响).

变量

所谓"变量",有两层含义:一是他是可以变化的量,取决于给他的赋值.

二他是某个内存地址的标识符,所以变量在知道数据地址的前提下,并不是必须存在的.---因为可以用地址(指针)来表示变量. 但是指针名和变量名的意义是相同的:让程序员清楚知道他代表的数据的含义以及占据的内存空间(基本数据类型的变量).例如:


double money;         //第1行
int number=10;        //第2行
int *p=new int{20};   //第3行

第1行的写法: 数据类型 变量名;

程序员从中获得的信息:

        新开辟了一块内存空间,占8个字节,表示money.内存空间在哪块未知;具体地址未知.

第2行写法:数据类型 变量名=值;

        信息:新开辟了内存空间,占4个字节,表示number,赋值10;同样内存空间和具体地址未知.

第3行的写法: 指针类型 指针名=new 数据类型{值}

        信息:在堆空间开辟了一块内存,大小4个字节,赋值20;在其他语句中可以用*p取得该地址值.

内存空间

内存空间为程序分配了三块:一是自动存储区,给自动变量,又被称为栈区,特点:后进先出.函数执行完毕后自动释放;                       二是静态存储区,给静态变量:特点:在程序运行期间一直存在.                                                             三是动态存储区,给new分配的内存空间,特点:可以用delete释放.

数据类型

数据类型可分为基本数据类型(内置数据类型)和复杂数据类型.复杂数据类型一般指结构和类.结构和类里包含基本数据类型成员或其他结构成员,类对象成员. 复杂结构类型和成员之间是一种包含关系.例如:

class person{
    std::string name;
    int age;
}

 一个表示"人"的类,用string对象表示名称,用一个int变量表示年龄.

程序的组织

程序由多个文件所组成,文件又称作"翻译单元".每个翻译单元由头文件.h和源文件.cpp组成.为什么要这样设计呢?有利于分工.比如每个文件里明确完成什么样的工作,再交由程序员完成.

文件内定义了数据类型和函数,常量.---和类有着相同的组成

其中main()函数所在的文件称为"主文件",他是程序的入口.文件之间的数据默认不可见.通过预处理指令"#include+文件名",使其他文件的内容可见,又称为作用域扩展.

变量分类及作用域

1.变量有什么样的作用?

变量是变化的量,他起的作用是传递数据. 变量一定有数据类型.相同数据类型的变量才可以赋值.

变量和函数是紧密联系在一起的.变量用得最多的就是接收函数返回值传入形参.在初学时常常为怎样传入参数而苦恼.有个简单的方法:形参是否能"等于"将要传入的变量.例如:

#include<iostream>

void show(const int* ivalue);

int main() {
    using namespace std;
    int a = 10;
    int b = 20;
    int* c = &b;
    show(&a);
    show(c);
}

void show(const int* ivalue) {
    std::cout << *ivalue << std::endl;
}

上述代码中形参类型为const int *,形参是ivalue.  以下赋值成立: 

        const int* ivalue=&a;       const int* ivalue=c;

所以可以把&a和c传给形参ivalue 

---------本例是为了简要说明,实际上不会这样用.一般说来传指针表示要传数组或者数据集合,单个数据把值传进去即可.这里的形参应写成const int ivalue,传整型常量如3或者整型变量a,b都可以.

#include<iostream>

void show(const int ivalue);

int main() {
    using namespace std;
    int a = 10;
    int b = 20;
    int* c = &b;
    show(a);
    show(3);
    show(*c);
}

void show(const int ivalue) {
    std::cout << ivalue << std::endl;
}

2.作用域的概念

作用域指能被程序访问到的区域."在某个作用域内"表示数据可见可用.否则要加上作用域访问符"::"

3.变量分类

变量分为:全局变量,全局静态变量,临时变量,局部静态变量这几种.用得最多的是临时变量.

----这几种叫法沿用了C语言. 书面语言叫外部链接,内部链接,无链接等

1>全局变量

        作用:在函数(一般是主文件中的函数)之间传递数据.作用域从定义位置到文件结束.

        全局变量一般放在主文件的main函数之前.但小程序通常用main函数里开始部分定义,即main函数的临时变量来代替.如果全局变量用得比较多,可单独放到一个文件,再用预处理指令#include包含进主文件.

        全局变量的const形式,一般叫做全局常量,是代替字面常量的符号常量,好处是避免文件中的硬编码以及增加程序可读性.

2>全局静态常量

        作用:在文件内部的函数间传递数据. 

        当文件被包含入主文件或其他文件时,不可使用. 全局静态变量容易产生混淆,可以不用.

3>临时变量

        作用:在函数内部传递数据.

        作用域从定义到代码块结束(),函数调用结束后自动释放内存空间.

4>局部静态变量

        作用:在调用函数间传递数据.

        最常见的用法是在函数内部定义一个静态变量记录调用次数.

名称空间

当有多个文件加入程序,这些文件可能是由不同厂商提供,可能产生数据同名的情况.如果不加限制,则同名数据(类,函数)会产生冲突 ,导致不希望发生的结果.因此C++加入了名称空间namespace来解决这种情况.

定义:namespace{},在大括号里加入数据类型定义或者函数定义.

---说明:名称空间具有开放性,即可以在多个文件中使用同一个名称的名称空间.但为了方便管理,通常把名称空间放进一个文件里.

data.h


namespace myNameSpace{
    struct mystruct{
        double money;
        int name;
    }
    void fun();

}

data.cpp

#include<iostream>
#include"data.h"


    void fun(){
        std::cout<<"it's a fun"<<std::endl;
}

main.h 

#include<iostream>
#include"data.h"

int main(){
    using myNameSpace::mystruct        //using声明结构类型
    using myNameSpace::fun             //using声明函数
    mystruct ms={100000000.00,"good"}  //使用结构类型创建结构数据
    fun();                             //调用函数
}

using声明表示当前文件获得了数据类型或者函数的使用权,在作用域中不能有其他同名数据出现,否则不能通过编译. 通常推荐采用using声明来表明数据.

另外有一种格式叫using编译指令:

using namespace + 名称空间名;   

//他的好处是方便,可以不用一个个using声明,但他不区分全局命名空间,局部变量,意思是在其使用数据处,可以定义其他同名变量,容易造成混淆.

自定义名称空间

using声明似乎解决了所有问题,但他不能避免过长的声明---如果需要声明的数据过多,会显得繁杂.所以有一种方法,就是自定义一个命名空间,然后用using编译指令导入到主文件中.

自定义名称空间可以使用using声明和using编译指令导入其他命名空间的数据或者整个命名空间.

mydata.h

#include<iostream>
#include"mydata2.h"
namespace myNameSpace {
    using namespace otherNameSpace;    //包含其他命名空间
    using std::cout;                   //声明cout
    using std::endl;                   //声明endl
}

 mydata2.h

#include<iostream>
namespace otherNameSpace {
    void fun() {
        std::cout << "it's ok" << std::endl;
    }
}

main.h

#include<iostream>
#include"mydata.h"

int main() {
    using namespace myNameSpace;    //使用using编译指令导入整个自定义命名空间
    cout << "hello world" << endl;
    fun();
}

---说明:按C++ Prime Plus Edition 6th上的写法会报错---把两个命名空间myNameSpace和OtherNameSpace放到一个文件"mydata.h"里在Vs里不可行.可能是VS版本已经不支持这种写法.但是问题不大,多写一个文件就解决了.

使用using编译指令导入命名空间的写法是不被推荐的,因为他可能会造成数据混淆.所以在用这种写法的时候,最好是程序员清楚的知道具体情况.或者不在主程序里另外使用数据.好处是程序看起来简洁. 实际运用中可以采用using编译指令和using声明相结合,根据实际情况使用.

  • 24
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jllws1

你的鼓励是我创作的动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值