C++ 基础 1:C++ 对 C 语言的增强

0
7

1 namespace 命名空间

1.1 C++ 命名空间的定义

C++标准 引入了关键字 namespace(命名空间),可以更好地控制标识符的作用域。

namespace name
{
      ...
}

1.2 C++ 命名空间的使用方法

std 是 C++标准命名空间,C++标准程序库中的所有标识符都被定义在 std 中,比如标准库中的类 iostream、vector 等,使用时要加上 using 声明(using namespace std)或 using 指示(std::string、std::vector<int>

  • 使用整个命名空间:using namespace name;

  • 使用命名空间中的变量:using name::variable;

  • 使用默认命名空间中的变量:::variable

1.3 头文件 <iostream> 和 <iostream.h> 的区别

<iostream> 和 <iostream.h> 两者是两个文件,里面的代码也不一样。早期的 C++ 实现将标准库功能定义在全局空间里,声明在 <iostream.h> 中。

而 C++ 标准为了和 C 区别开来,也为了正确使用命名空间,规定头文件不使用后缀.h。因此,

  1. 当使用 <iostream.h> 时,相当于在 C 中调用标准库函数,使用的是全局命名空间,也就是早期的 C++ 实现。

  2. 当使用 <iostream> 时,该头文件没有定义全局命名空间,必须使用 namespace std,才能正确的使用标准库函数如 cout。

1.4 C 和 C++ 中的命名空间的区别

C 中的命名空间

  • 在 C 语言中只有一个全局作用域

  • C 语言中所有的全局标识符共享同一个作用域

  • 标识符之间可能发生冲突

C++ 中的命名空间

  • 命名空间将全局作用域分成不同的部分

  • 不同命名空间中的标识符可以同名而不会发生冲突

  • 命名空间可以相互嵌套

  • 全局作用域也叫默认命名空间

1.5 C++ 命名空间编程实践

// naspaceTest.cpp,本代码验证 namespace 作用域
// C 语言头文件,C++ 兼容 C 语言
#include<stdio.h>

namespace namespaceA
{
	int variable = 0;
}

namespace namespaceB
{
	int variable = 1;

	namespace namespaceC
	{
		int variable;

		struct infoStruct
		{
			char name[10];
			int age;
		};
	}
}

int main(void)
{
	using namespace namespaceA;

	printf("namespaceA variable = %d\n",variable);	//0

	printf("namespaceB variable = %d\n",namespaceB::variable);	//1

	namespaceB::namespaceC::variable = 2;

	printf("namespaceC variable = %d\n",namespaceB::namespaceC::variable);	//2

	namespaceB::namespaceC::infoStruct info = {"Pika",16};
	
	printf("namespaceC.info.name = %s\n",info.name);	//Pika
	printf("namespaceC.info.age = %d\n",info.age);	//16

	getchar();

	return 0;
}

运行结果:

2 变量定义位置

C 语言:在较老的 C89/C90 标准(ANSI C标准)下,变量只能在程序的开头定义,或者说变量定义的前面不能有其他非声明或非定义的语句。

比如在 VC++6.0 或者 VS2010 下编译以下代码时:

// varDefTest.c,本代码验证在较老的 C89/C90 标准(ANSI C标准)下,变量定义位置
# include <stdio.h>
int main(void)
{
    int i;
    i = 1;
    int j = 2;  //这句是错误的,因为在它前面有一个给变量 i 赋值的非定义语句
    return 0;
}

会提示下面的错误:

error C2143: 语法错误 : 缺少“;”(在“类型”的前面)

但是这种写法在 .cpp 文件(C++ 源文件)中是允许的,C++ 允许在程序的任意位置定义变量。

3 全局变量重复定义检测

在 C 语言中,允许重复定义多个同名的全局变量,多个同名的全局变量最终会被链接到全局数据区的同一个地址空间上,即全局变量会取最后一个被赋予的值,如下所示:

// globalValTest.c,本代码验证在 C 语言中,允许重复定义多个同名的全局变量
#include <stdio.h>

int global_val;

int global_val = 1;

int main()
{
	printf("global_val = %d\n",global_val);

	return 0;
}

运行结果:

在 C++ 中不允许定义多个同名的全局变量,如下所示:

// globalValTest.cpp,本代码验证在 C++ 中不允许定义多个同名的全局变量
#include <iostream>

using namespace std;

int global_val;
int global_val = 1;

int main(int argc, char *argv[])
{
        cout << "global_val = " << global_val << endl;

	return 0;
}

运行结果:

4 struct 类型

C 中的 struct 只能是一些变量的集合体,可以封装数据却不可以隐藏数据,而且成员不可以是函数。

C++ 中的 struct 可以当作 class 来用,在标准 C++ 中,struct 和 class 有两个区别:

  1. struct中的成员默认是 public 的,class 中的默认是 private 的。

  2. 在用模版的时候只能写 template 或 template 不能写 template 。

此外,如果没有多态和虚拟继承,在 C++ 中,struct 和 class 的存取效率完全相同。

如果不是为了和 C 兼容,C++ 中就不会有 struct 关键字。因此建议是:如果不需要与C兼容或传递参数给C程序,不要在 C++ 中用 struct。

5 C++ 相较 C 更加强类型,任意位置的程序元素都必须显式指明类型

C 语言中,默认类型包括以下情况:

  • 如果没有明确写出函数返回类型,函数返回类型默认为 int 类型。

    例:function(int arg); ,表示返回值为 int ,接受一个 int 类型参数的函数。

  • 如果没有明确写出函数参数类型,函数参数默认为 int 类型。

    例:int function(arg); ,表示返回值为 int ,接受一个 int 类型参数的函数。

  • 如果没有明确写出函数参数,则该函数可以接受任意参数。

    例:int function(); ,表示返回值为 int,接受任意参数的函数。

C 语言中的默认类型在 C++ 中是不合法的。

在 C++ 中,int function();int function(void) 具有相同的意义,都表示返回值为 int 的无参函数。

6 新增 bool 类型关键字

C++ 在 C 语言的基本类型上增加了 bool 类型,bool 类型只有 true(非0),false(0)两个值。

7 三目运算符功能增强

C 语言中的三目运算符返回的是变量的值,不能作为左值使用。

C++ 中的三目运算符可直接返回变量本身,因此可以出现在程序的任何地方。

但三目运算符可能返回的值中如果有一个是常量,则不能作为左值使用,如:(a<b?1:b) = 30;

8 const 增强

8.1 C++ const关键字小结

const 关键字用来定义常量。

常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。

8.1.1 const 修饰普通类型的变量

const int CONST_A = 1;      // 常整型数 CONST_A

int const CONST_B = 2;      // 常整型数 CONST_B

int c = CONST_A;            // 正确

CONST_A =  3;               // 编译器会报错,给常量赋值是不被允许的

可以将 常整型数 CONST_A 赋值给 整型变量 c,但是不能给 常整型数 CONST_A 再次赋值。对一个常量赋值是不被允许的,常量的值不允许修改。

8.1.2 const 修饰指针变量

const int *CONST_P_C = 1;     // CONST_P_C是一个指向常整型数的指针(它所指向的内容不能被修改,但是指针指向的内存地址可以修改)

int test = 61;

*CONST_P_C = 0;      // 编译器不允许,报错

CONST_P_C = &test;   // 正确


int* const CONST_P_D = 2;     // CONST_P_D是一个常指针(指针指向的内存地址不能被修改,但是它所指向的内容可以被修改)

*CONST_P_C = 0;      // 正确

CONST_P_C = &test;   // 编译器不允许,报错


const int * const CONST_P_E = &test;   // CONST_P_E是一个指向常整型数的常指针(指针指向的内存地址和她所指向的内容,均不能被修改)

8.2 const 和 #define 的区别

const 常量是由编译器处理的,提供类型检查和作用域检查。

#define由预处理器处理,单纯的文本替换。

8.3 C 语言和 C++ 中的 const 区别

8.3.1 C 语言中的 const 变量

C 语言中的 const 变量是只读变量,有自己的存储空间

8.3.2 C++ 中的 const常量

  • 可能分配存储空间,也可能不分配存储空间

  • 当 const 常量为全局时,并且需要在其他文件中使用,会分配存储空间

  • 当需要使用 & 操作符,取 const 常量的地址时,会分配存储空间

  • const int &a = 10; ,即 const 修饰引用时,也会分配存储空间

9 对 enum 枚举的检测增强

C 语言中枚举的本质就是 int,枚举变量可以用任意 int 赋值。但 C++ 中,只能用被枚举出来的元素赋值,如下所示:

// enumTest.cpp,本代码验证 枚举

#include <iostream>
using namespace std;

enum sex{girl,boy};

int main()
{
	enum sex testSex = girl;
        
        testSex = 0; // 错误,但是 C 语言能通过
        
        testSex = boy;  

        cout << "testSex = " << testSex << endl; // 1      

	return 0;
}

<

发布回复

请输入评论!
请输入你的名字