重庆可做网站 APP,阿里云域名注册查询,什么 门户网站,湖北省住房城乡建设厅网站首页文章目录 前言一、C命名空间1.1 命名空间的定义1.2 命名空间的使用 二、C的输入和输出2.1 cin和cout的使用 三、缺省参数3.1 缺省参数的分类 四、函数重载4.1 函数重载概念及其条件4.2 C支持函数重载原理 -- 名字修饰 前言
C是在C语言的基础之上#xff0c;增加了一些面向对象… 文章目录 前言一、C命名空间1.1 命名空间的定义1.2 命名空间的使用 二、C的输入和输出2.1 cin和cout的使用 三、缺省参数3.1 缺省参数的分类 四、函数重载4.1 函数重载概念及其条件4.2 C支持函数重载原理 -- 名字修饰 前言
C是在C语言的基础之上增加了一些面向对象的编程思想增加了一些有用的库所以有了学习C语言的经验学习C其实很容易的。至于C初阶我们可以认为C的出现其实就是为了弥补C语言在某些方面的不足之处。所以从这篇开始一起来学习C以及C到底弥补了C语言的哪些不足。
一、C命名空间
学过C的人都知道在学习C的过程中比如在某些视频教程中教我们写的第一个程序往往都是打印hello world但是每次在写的过程中老师们都叫我们去忽略一些东西比如using namespace std 那这句话到底有什么用呢
无论是C语言还是C在同一个局部域里面是不允许出现相同的变量名的在同一个作用域下定义了两个相同变量名的变量会导致访问冲突编译器不知道该使用哪个变量从而导致报错。不仅仅是变量名函数名相同也是一样的C函数重载除外。这也导致在一群人写同一个项目时写完在合并之后可能导致函数名或变量名冲突的问题为解决这个问题C的命名空间孕育而生。
命名空间的目的就是对标识符的名称进行本地化避免命名冲突或名字污染namespace关键字就是为了解决这样的问题。
1.1 命名空间的定义
定义命名空间时需要用到namespace这个关键字后面紧跟命名空间的名字再接一队 {}{} 中为命名空间的成员。 一个命名空间就是定义了一个新的作用域命名空间的所有内容都局限于这个命名空间中。
namespace N1 // 命名空间N1
{int a 10;void test(){printf(test() a 10\n);}
}namespace N2 // 命名空间N2
{int a 20;void test(){printf(test() a 20\n);}namespace N3 // 命名空间N3, 命名空间的嵌套{struct Node{struct Node* next;int data;};}
}1.2 命名空间的使用
要使用命名空间的内容有三种方法第一种就是命名空间名称加作用域限定符。 格式命名空间名称::命名空间成员
int main()
{printf(%d\n, N1::a); // :: 是作用域限定符N1::test();printf(%d\n, N2::a);N2::test();N2::N3::Node node;node.data 123;printf(%d\n, node.data);return 0;
}方法二使用using将某个命名空间的某个成员引入。 格式using 命名空间名称::命名空间成员
using N1::a; //
using N2::N3::Node;
int main()
{printf(%d\n, a);printf(%d\n, N2::a);Node node;node.data 456;printf(%d\n, node.data);return 0;
}方法三使用using namespace 命名空间名称引入。不推荐 格式using namespace 命名空间名称
using namespace N2;int main()
{printf(%d\n, a);test();printf(%d\n, N1::a);N1::test();N3::Node node;node.data 789;printf(%d\n, node.data);return 0;
}注意使用 using namespace 命名空间名称 就相当于破坏了作用域之间的封闭性将命名空间中的成员全部暴露出来了。在日常练习中建议直接using namespace std即可这样就很方便。
了解完命名空间后我们也算知道了为什么每次写C程序时总要写一句using namespace std std::是个名称空间标识符C标准库中的函数或者对象都是在命名空间std中定义的所以我们要使用标准库中的函数或者对象都要用std来限定。
C标准库C Standard Library是类库和函数的集合其使用核心语言写成由c标准委员会制定并不断维护更新。
using std::cout; // 分别将cout和endl释放出来
using std::endl;int main()
{cout N1::a endl;cout N2::a endl;N2::N3::Node node;node.data 111;cout node.data endl;return 0;
}二、C的输入和输出
C作为一门新的语言不但可以兼容C语言C自己也有属于自己的独有语法最典型的就是C不仅可以使用C语言中的printf和scanf也可以使用自己的输入输出语句cout输出 和 cin输入这两个都是全局的流对象endl是特殊的C符号表示换行。 cout标准输出对象控制台和cin标准输入对象键盘都必须包含iostream头文件以及按照命名空间使用方法使用std。 cout和cin分别是ostream和istream类型的对象 和 分别是流插入运算符和流提取运算符实际是运算符重载过来的。
2.1 cin和cout的使用
#includeiostream
using std::cout;
using std::cin;
using std::endl;int main()
{int a 0;cin a; // cin和cout可以自动识别类型cout a endl;return 0;
}三、缺省参数
缺省参数就是在给函数声明或定义时给函数的参数一个默认的值在调用该函数时如果没有给函数传递实参的话该函数调用时就会采用该形参的缺省值如果调用时传递了实参就采用指定的实参。
void test1(int a 20)
{cout a endl;
}int main()
{int a 10;test1(); // 没有传参时使用参数的默认值test1(a); // 有参数传递时使用指定的实参return 0;
}3.1 缺省参数的分类
全缺省参数
函数的每个参数都有自己的默认值这样的参数就是全缺省参数。
void test2(int a 10, int b 20, int c 30)
{}半缺省参数
函数的部分参数有默认值其余参数没有参数值。
void test3(int a, int b 10, int c 20)
{}半缺省参数必须从右往左依次给中间不能间隔传参时也无法指定传参。另外函数的缺省值不能再声明和定义中同时出现。那么函数的缺省值是在函数的声明给还是在函数的定义时给呢
其实只要我们仔细想一下就应该知道缺省值应该在函数的声明时给因为函数往往都是先声明后使用如果我们在声明函数时没有缺省值但定义时又给了缺省值就容易导致声明与定义不一致另外修改函数的声明比修改函数的定义要方便。
注意函数的缺省值必须要是常量或则是全局变量C语言不支持缺省参数其实就是C语言的编译器不支持。
四、函数重载
4.1 函数重载概念及其条件
自然语言中存在一词多义的现象其意思需要人去结合上下文去判断这就是词的重载所以函数重载就是C中允许同一个作用域中拥有功能相似的同名函数同名函数之间的形参列表形参类型、个数、类型顺序不同来处理一些功能类似数据类型不同的问题。
以下四个test01函数都构成函数重载。
// 参数个数不同
void test01()
{cout test01() endl;
}
// 参数类型不同
void test01(int a)
{cout test01(int a) endl;
}
// 参数类型顺序不同
void test01(int a, double b)
{cout test01(int a, double b) endl;
}void test01(double a, int b)
{cout test01(double a, int b) endl;
}注意函数的返回值不构成函数重载因为只有返回值相同的话会造成调用歧义编译器不知道该调用哪个函数从而编译报错。
4.2 C支持函数重载原理 – 名字修饰
C为什么可以支持函数重载而C语言为什么不可以支持 学习C语言的时候可以知道一个程序要运行起来需要经历四个阶段预处理、编译、汇编、链接。 编译之后会有一个符号表函数会有自己的名字修饰像Windows中VS的函数名修饰规则有点复杂我们可以通过Linux下的gcc来查看函数名修饰规则。 在Linux下我们可以先用gcc编译一下C语言代码然后通过objdump -S 可执行文件来查看这个汇编代码从而看C语言下的函数名修饰规则。 通过汇编代码可以看到C语言下函数名就是修饰后的名字。所以如果C语言中有两个名字相同的函数那么修饰后的名字也是一样的编译器不知道该调用哪一个导致编译报错。
现在我们用g去编译C的代码然后去看一下汇编后函数名会修饰成什么样子。 通过汇编代码可以看到C不是单纯的用函数名进行修饰的在函数名的前面加了一个 _Z 的前缀函数名的后面是函数参数类型的缩写id就表示该函数的参数类型是int和double类型而di就表示该函数的参数类型是double和int类型通过函数调用时传递的实参类型决定调用哪一个函数。不会存在调用冲突的问题。
这也就是为什么C语言为什么不能支持函数重载的原因同名函数编译后无法区分而C通过函数名修饰规则来区分只要参数不一样修饰出来的名字就不一样也就支持了函数重载。