欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 14_C++对c的扩展

14_C++对c的扩展

2024/10/24 18:27:31 来源:https://blog.csdn.net/weixin_51253120/article/details/141938341  浏览:    关键词:14_C++对c的扩展

c++对c的扩展

1 作用域运算符(重要)

符号

::

作用:

1,当局部变量与全局变量重名时,区分局部变量与全局变量变量名 局部变量::变量名 全局变量
2,指明使用的变量所属的命名空间命名空间名::变量名
3,实现函数的声明与定义分离如:
namespace E
{void method02();//函数的声明
}
void E::method02()//函数的定义(实现)
{
}

如:C中代码

#include <stdio.h>
int num = 10;
int main(int argc, char const *argv[])
{int num = 20;printf("局部变量num = %d\n", num);// 在c语言中当局部变量与全局变量重名时,因为就近原则,默认使用的是局部变量// 此时无法使用全局变量return 0;
}

如:c++代码

#include <iostream>
using namespace std;
int num = 10;
int main(int argc, char const *argv[])
{int num = 20;cout << "局部变量 num = " << num << endl;cout << "全局变量 num = " << ::num << endl;return 0;
}

2 namespace与using(重要)

namespace

含义

命名空间

语法

namespace 空间名
{//变量//函数
}

注意

1,命名空间只能全局范围内定义(必须定义在函数外)
2,命名空间可嵌套命名空间
3,命名空间是开放的,即可以随时把新的成员加入已有的命名空间中
4,声明和实现可分离
5,无名命名空间,意味着命名空间中的标识符只能在本文件内访问
6,命名空间别名

示例1

#include <iostream>
using namespace std;
namespace A
{int a = 1;int b = 11;char c = 'A';
}
namespace B
{int a = 2;int b = 22;char c = 'B';
}
// 命名空间可以嵌套
namespace C
{int a = 4;namespace D{int a = 5;}
}
// 命名空间是开放的,即可以随时把新的成员加入已有的命名空间中
// 不能在次定义相同的变量
namespace A
{int d = 111;
}
namespace E
{// 命名空间中可以定义函数void method01(){cout << "method01" << endl;}// 声明和实现可分离void method02();
}
void E::method02()
{cout << "method02" << endl;
}
// 无名命名空间
namespace
{int a = 6;
}
int main(int argc, char const *argv[])
{int a = 3;cout << "A a = " << A::a << endl;cout << "B a = " << B::a << endl;cout << "a = " << a << endl;cout << "C a = " << C::a << endl;cout << "D a = " << C::D::a << endl;cout << "A d = " << A::d << endl;cout << "无名 a = " << ::a << endl;E::method01();E::method02();return 0;
}

示例2

#include <iostream>
using namespace std;
namespace A
{int a = 1;
}
int main(int argc, char const *argv[])
{// 命名空间别名namespace A1 = A;cout << "A a = " << A::a << endl;cout << "A1 a = " << A1::a << endl;return 0;
}

using

作用:

声明可使得指定的标识符可用

语法:

1,声明命名空间中单个变量using 命名空间名::变量名;
2,声明命名空间中单个函数using 命名空间名::函数名;
3,声明整个命名空间using namespace 命名空间名;

示例:

#include <iostream>
using namespace std;
int main()
{int i =  10;char c = 'A';void methodA(){cout<<"methodA"<<endl;}
}
//声明命名空间中的单个变量
//声明后在使用该变量就可以直接使用
using A::i;
//声明命名空间中的单个函数
//声明后在使用该函数就可以直接使用
using A::methodA;
//声明整个命名空间
//声明后整个命名空间中所以内容都可直接使用
using namespace A;
int main(int argc, char const *argv[])
{cout << "A i = " << A::i << endl;cout << "A i = " << i << endl;methodA();
cout << "A c = " << c << endl;return 0;
}

注意:

> using遇到函数重载,using 声明就声明了这个重载函数的所有集合。>	重载:同一片空间中,函数名相同,形参列表不同,成为重载c语言不支持重载c++支持重载使用 using 声明或 using 编译指令会增加命名冲突的可能性。

3 全局变量检测增强

如c:

#include <stdio.h>
int a; // c语言编译器会认为此处为变量的声明
int a;
int a = 10; // 变量的定义与初始化
int main(int argc, char const *argv[])
{return 0;
}

如:c++

#include <iostream>
using namespace std;
int a; 				// c++编译器将此处理解为变量的定义
// int a = 10;		//此时将会重复定义,程序无法编译通过
int main(int argc, char const *argv[])
{return 0;
}

3.1 C++中所有变量和函数都必须有类型

如:c

#include <stdio.h>
void fun(i)
{printf("fun\n");
}
void fun02()
{printf("fun02\n");
}
int main(int argc, char const *argv[])
{fun(10);fun02();return 0;
}

如:c++

#include <iostream>
using namespace std;
// c++中变量必须有类型,此时i没有类型所有无法编译通过
//  void fun(i)
//  {
//  }
// 形参中的void表示没有形参列表
void fun02(void)
{cout << "fun02\n";
}
int main(int argc, char const *argv[])
{fun02();return 0;
}

3.2 更严格的类型转换

如:c编译通过

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{int *nums = calloc(10, sizeof(int));return 0;
}

c++,必须强转后才可通过

#include <iostream>
#include <stdlib.h>
using namespace std;
int main(int argc, char const *argv[])
{int *nums = (int *)calloc(10, sizeof(int));return 0;
}

3.3 struct类型加强(掌握)

c 中定义结构体变量需要加上 struct 关键字,c++不需要。

c 中的结构体只能定义成员变量,不能定义成员函数。c++即可以定义成员变量,也可以定义成员函数

示例:

#include <iostream>
using namespace std;
struct Person
{char name[50];int age;void eat(){cout << name << "吃面条" << endl;}void game();
};
void Person::game()
{cout << name << "玩游戏" << endl;
}
int main(int argc, char const *argv[])
{// c语法struct Person p1 = {"tom", 18};// c++语法,定义结构体变量时可以不用写struct关键字Person p2 = {"jek", 18};p1.eat();p2.eat();p1.game();return 0;
}

3.4 新增bool类型

关键字

bool 数据类型
true 真
false 假
true(转换为整数 1)false(转换为整数 0)
bool类型的变量取值:true或false
bool 类型赋值时,非 0 值会自动转换为 true(1),0 值会自动转换 false(0)

注意

c 语言中也有 bool 类型,在 c99 标准之前是没有 bool 关键字,c99 标准已经有 bool 类型,包含头文件 stdbool.h,就可以使用和 c++一样的 bool 类型。

示例

#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{cout << true + 0 << endl;cout << false + 0 << endl;bool tag = true;tag = false;tag = 10;cout << tag << endl;return 0;
}

3.5 三目运算符功能增强

# 	c语言三目运算符返回的是值
#	c++三目运算符返回的是变量

如c

#include <stdio.h>
int main(int argc, char const *argv[])
{int a = 10;int b = 1;// c语言中三目返回的是值,不是变量int c = a > b ? a : b;// 所以三目在c中不能作为左值,无法通过编译(a > b ? a : b) = 100;return 0;
}

如:c++

#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{int a = 10;int b = 1;// c++中三目返回的是变量,不是值int c = a > b ? a : b;// 所以三目在c++中可以作为左值(a > b ? a : b) = 100;cout << "a = " << a << endl;return 0;
}

4 C/C++中的const

全局变量

c

#include <stdio.h>
const int num = 10;
int main(int argc, char const *argv[])
{// const修饰的变量不能重新赋值// num = 1;// 无法进行修改,因为num的值存储在常量区int *p = &num;*p = 1;printf("num = %d\n", num);printf("*p = %d\n", *p);return 0;
}
// 出现段错误

c++

#include <iostream>
using namespace std;
const int num = 10;
int main(int argc, char const *argv[])
{// num = 1;int *p = (int *)&num;*p = 1;cout << "num = " << num << endl;cout << "*p = " << *p << endl;return 0;
}
// 出现段错误
#include <iostream>
using namespace std;
struct Person
{int age;
};
const Person p = {2};
int main(int argc, char const *argv[])
{Person *p1 = (Person *)&p;p1->age = 10;cout << "p.age = " << p.age << endl;return 0;
}

局部变量

c

#include <stdio.h>
int main(int argc, char const *argv[])
{const int num = 10;// const修饰的变量不能重新赋值// num = 1;// 可以进行修改,因为num的值存储在栈区int *p = &num;*p = 1;// 修改完成后num的值也将被修改printf("num = %d\n", num);printf("*p = %d\n", *p);return 0;
}

c++

#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{// 在c++中const修饰的变量会存储在常量表中const int num = 10;// num = 1;// 当我们对常量表的中的变量区地址时,系统会开辟一片内存,使其存储其变量的值int *p = (int *)&num;// 此时使用指针对其修改,修改的是新开辟的内存中的值*p = 1;// 此时num的值依旧从常量表中获取,值并没有发生改变cout << "num = " << num << endl;cout << "*p = " << *p << endl;return 0;
}
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{int a = 10;// 在c++中const修饰的变量以其他变量初始化,会为其分配内存空间const int num = a;// num = 1;int *p = (int *)&num;*p = 1;// 此时num的值依旧从常量表中获取,值发生改变cout << "num = " << num << endl;cout << "*p = " << *p << endl;return 0;
}
#include <iostream>
using namespace std;
struct Person
{int age;
};
int main(int argc, char const *argv[])
{const Person p = {2};// const修饰自定义类型的变量,无法修改其自定义变量中的成员变量// p.age = 10;// 无法获取其成员变量的地址// int *p = &(p.age);// const修饰的自定义类型的变量,无法获取其地址,因为地址是使用const 数据类型 *修饰的// 转换后就可以使用该指针修改其自定义类型中的成员变量Person *p1 = (Person *)&p;p1->age = 10;cout << "p.age = " << p.age << endl;return 0;
}

总结(背诵)

全局变量:c/c++没区别,会出段错误
局部变量:1,如果const修饰的普通类型的变量,使用常量初始化如:const int a = 10;此时会生成符号表,当获取其变量的地址时会开辟新的地址,使用获取的地址
修改其值,不会影响符号常量表中的数据2,如果const修饰的普通类型的变量,使用变量初始化如:int y = 10;const int x = y;此时不会生成符号常量表,会直接开辟地址,存储该变量,获取的地址修改其值,会修改其内容.int *p =(int *)&x;*p = 1;cout << x << endl;   //1cout << *p << endl;  //13,如果const修饰的是自定义变量1,无法直接修改其自定义类型中的成员变量2,无法获取自定义类型中的成员变量的地址3,获取其自定义类型变量的地址需强转,强制过会就可以使用该地址修改其成员变量的值

建议

尽量以 const 替换#define
const与#define的区别1.const 有类型,可进行编译器类型安全检查。#define 无类型,不可进行类型
检查.2.const 有作用域,而#define 不重视作用域,默认定义处到文件结尾.如果定义在指定作用域下有效的常量,那么#define 就不能用

5 引用【重要】

英文名:reference

符号: &

作用: 给已有变量起别名

语法:

基本数据类型数据类型 &变量A = 变量B;给变量B取别名叫变量A此时操作A就是在操作B,操作B就是在操作A
数组类型方式1:typedef 数组的数据类型 类型别名[数组长度];类型别名 &别名 = 数组名;方式2:【*】数组的数据类型 (&别名)[数组长度] = 数组名;注意:此时数组长度不能忽略不写
指针数据类型 *&别名 = 指针变量名;
常量const 数据类型 &别名 = 变量名;

注意

1,不能返回局部变量的引用
2,函数当左值,必须返回引用。

本质

引用的本质在 c++内部实现是一个指针常量.
Type& ref = val;   // Type* const ref = &val;

#include <iostream>
using namespace std;
struct Stu
{int age;
};
// void test(Stu s)
// {
// s.age = 10;
// }
void test(Stu &s)
{s.age = 10;
}
int main(int argc, char const *argv[])
{Stu stu = {1};test(stu);cout << "stu.age = " << stu.age << endl;return 0;
}

6 内联函数(了解)

语法

inline 返回值类型 函数名(形参列表)
{函数体
}

特点

内联函数:在编译阶段像宏一样展开。
作为类的成员函数,有作用域的限制
内联函数为了继承宏函数的效率,没有函数调用时开销,然后又可以像普通函数样,
可以进行参数,返回值类型的安全检查,又可以作为成员函数

注意:取决于编译器

1,inline只能在定义函数的时候修饰。
2,任何在类内部定义的函数自动成为内联函数。
3,inline修饰的函数是否为内联函数,取决于编译器。对于非inline修饰的函数,也	有可能转成内联函数(体积小、功能简单的函数)。

条件

#	不能存在任何形式的循环语句
#	不能存在过多的条件判断语句
#	函数体不能过于庞大
#	不能对函数进行取址操作
宏函数和内联函数区别(重要)
宏函数(带参宏):参数没有类型,不能保证参数的完整型。宏函数 在预处理阶段展开。宏函数 没有作用域限制 不能作为类的成员。
内联函数:参数有类型 保证参数的完整型。内联函数 在编译阶段 展开。内联函数 有作用域限制 能作为类的成员

7 对函数的加强(重要)

形参默认值

语法

返回值类型 函数名(数据类型 变量名1 = 值,数据类型 变量名2 = 值,...)
{函数体
}

注意

形参中有默认值的参数,在函数调用时可传可不传,如果不传使用默认值
调用有默认值的函数,传入实参依据会按形参的顺序赋值
如果某个形参有默认值,其后的形参必须也有默认值

8 形参占位符

如:

void test(int a, int, int)
{
}
// 无论占位符在前还是后 中间也都行
void test(int, int a, int, int)
{
}
// 只有对应有形参的数 参与计算  占位符 只是占位置 没用
1,形参占位符可以有多个 
2,可以在形参的任意位置

9 重载

函数名相同,形参列表不同,称为重载
多态的一种体现

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com