C++对C的增强

一、namespace命名空间

1.C++命名空间基本常识
所谓namespace,是指标识符的各种可见范围。c++标准程序库中的所有标识符都被定义与一个名为std的namespace中。
1.1:<iostream>和<iostream.h>格式不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的,后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和c区别开,也为了正确使用命名空间,规定有文件不适用后缀.h。因此,
(1)当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的 c++实现;
(2)当使用<iosream>时,该头文件没有定义全局命名空间,必须使用namespace std;
这样才能正确使用cout;
1.2:由于namespace的概念,使用c++标准程序库的任何标识符时,可以有三种选择:
(1)直接指定标识符,例如std::ostream而不是ostream。完整语句如下:

std::cout <<std::hex << 3.4 <<std:endl;

(2)使用using关键字。using std::cout;using std::endl;using std::cin;以上程序可以写成

cout << std::hex <<3.4 <<endl;

(3)最方便的就是使用using namespace;例如, using namespace std;这样命名空间std内定义的所有标识符都有效(曝光)。就好像让门被声明为全局变量一样。那么以上语句可以如下写:

cout << hex <<3.4 <<endl;

因为标准库非常庞大,所以程序员在选择的类的名臣干活函数名时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字重涂,就把标准库中的一切都放在名字空间std中。但这又会带来一个新的问题。无数原有的c++代码都依赖于使用了多年的为标准库中的功能,他们都是在全局空间下的。所以就有了<iostream>和<iostream>等等这样的头文件,一个是为了兼容以前的c++代码,一个是为了智齿新的标准。命名空间std封装的是标准程序库的名称,标准程序库为了和以前的头文件区别,一般不加“.h”。

2.C++命名空间定义及使用语法
在c++中,名称(name)可以是符号常量、变量、宏、函数、结构、枚举、类和对象等等。为了避免,在大规模程序的设计中,以及在程序员使用各种各样的c++库时,这些标识符的命名发生冲突。
标准库c++引入了关键字namespace(命名空间/名字空间/名称空间/名域),可以更好地控制标识符的作用域。
std时c++标准命名空间,c++标准程序库中的所有标识符都被定义在std中,比如标准库中的类iostream,vector等都定义在该命名空间中,使用时要加上using声明(using namespace std;)或using 指示(如:std::string;std::vector<int>;)

c中的命名空间
在c语言中只有一个全局作用域。
c语言中所有的 全局标识符共享一个作用域。
标识符之间可能发生冲突。
c++中提出了命名空间的概念
命名空间将全局作用域分成不同的部分
不同命名空间中的标识符可以同名而不会发生冲突。
命名空间可以相互嵌套。
全局作用域也叫默认命名空间

c++命名空间的定义
namespace nameA{...};
c++命名空间的使用
使用整个命名空间:using namespace nameA;
使用命名空间中的变量:using naeA::variable;
使用默认命名空间中的变量:::variable;
默认情况下可以直接使用默认命名空间中的所有标识符。

3.C++命名空间编程实践

#include <iostream>
using namespace std;

namespace namespaceA{
int a=10;
}

namespace namespaceB{
int a=1;
namespace namespaceC{
struct Teacher{
char name[10];
int age;
}
}
}
int main()
{
using namesapce nameSpaceA;
using namespaceB::namespaceC::Teacher;
printf("a = %d
",a);
printf("a = %d
",namespaceB::a);

Teacher t1={"aaa",33};
printf("t1.name = %s
",t1.name);
printf("t1.age = %d
",t1.age);
return 0;
}

4.结论
(1)当使用<iostream>时,该头文件没有定义全局命名空间,必须使用namespace std;
这样才能正确使用couot。若引入using namespace std;需要这样做。std::cout。
(2)c++标准为了和c区别开,也为了正确使用命名空间,规定头文件不适用后缀.h。
(3)c++命名空间的定义:namespace name{...};
(4)using namespace namespaceA;
(5)namespace 定义可嵌套。

二、“实用性”加强
#include"iostream"
using namespace std;
//c语言中的变量都必须在作用域开始的位置定义!
//c++中更强调语言的“实用性”,所有的变量都可以在需要使用时定义。

int main11()
{
  int i=0;
  printf("ddd");
  int k=0;
  return 0;
}

  


三、register关键字加强
在C语言中有这么一个关键字——register,这个关键字的意思就是告诉编译器,最好把该关键字修饰的变量放在寄存器内。关于这个关键字还有一些注意点要学一下。

注意:register是最快的关键字。cpu不直接跟内存打交道,需要通过寄存器做中转。

1.被register修饰的变量必须是CPU能够接受的类型,因为有的机器识别不了浮点型,所以register变量的长度应该小于等于整形,但现在有的机器是可以使用浮点型的register变量的。

2.在C语言中,一旦声明为寄存器变量,由于可能会保存到寄存器中,编译器是不允许对其取地址(&)的

3.只有局部自动变量和形参可以是寄存器变量,比如在C语言中,全局变量是不能用register修饰的,并且局部静态变量也不能用register修饰

4.register变量的个数是有限的,因为一个CPU只有那么多个寄存器,并且类型也会受到CPU的限制,并且某些寄存器只能接受特定的类型,如指针类型

开头也说了,这个关键字只是告诉编译器最好将被修饰的变量放到寄存器中以加快存取速度,但是是否真正的存储的寄存器由编译器自己决定。

而在C++中,该关键字又有几点不同:
(1)register 关键字无法在全局中定义变量,否则会被提示为寄存器无效。其实这一点在新的gcc编译器下C语言也不允许定义全局的register变量,因为生命周期直到程序结束,期间都作为寄存器变量的话明显不妥。
(2)register 关键字在局部作用域中声明时,可以用 & 操作符取地址,一旦使用了取地址操作符,被定义的变量会强制存放在内存中

//register关键字,请求编译器让变量a直接放在寄存器里面,数据块。
//在c语言中register修饰的变量,不能去抵制,但是在c++里面做了内容。
/*
1、
register关键字的变化。
register关键字请求“编译器”将局部变量存储与寄存器中。
  C语言中无法取的register变量地址
在c++中依然支持register关键字。
  c++中可以取得regiter变量的地址
2、
c++编译器发现程序中需要取register变量的地址时,register对变量的声明变得无效。
3、
早期c语言编译器不会对代码进行有话,因此register变量是一个很好的补充。
*/

int main22()
{
  register int a=0;
  printf("&a=%x ",&a);   return 0; }


四、函数类检测加强

在c语言中,重复定义多个同名的全局变量时合法的
在c++中,不允许定义多个同名的全局变量

c语言中多个同名的全局变量最终会被链接到全局数据区的同一个地址空间
int g_val;
int g_val=10;

c++拒绝这种二义性的做法

int main(int argc,char *argv[])
{	
  printf("g_var = %d 
",g_val);
  return 0;
}

五、struct类型加强

C语言的struct定义了一组变量的集合,C编译器并不认为这是一种新的类型。内不能定义函数。

C++中的struct是个新类型的定义声明。内可以定义函数。

C++中struct和class的用法几乎相同,区别是struct内默认是public的,class内默认是private。

struct Student
{
  public:
     char name[100];
     int age;
   int getall(char []n,int a);
  private:
    int score;
         
};
Student::getall(char []n,int a)
{
  cout<< "name=" << n <<endl;
  cout<< "age=" << a << endl;
}
int main(int argc ,char *argv[])
{
    Student s1={"wang",1,88};
    Student s2={"zhang",2,99};
    
     return 0;
}

    

六、C++中所有的变量和函数都必须有类型

/*

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

  c语言中的默认类型在c++中时不合法的

函数f的返回值是什么类型,参数又是什么类型?

函数g可以接受多少个参数?

*/

//更换成.cpp试试

f(i)//c++标准些微int f(int i)
{
  printf("i=%d
",i);
}

g()//c++标准写为int g()
{
  return 8;
}

int main()
{
  f(10);
  printf("g()=%d
",g(1,2,3,4,5));
  getchar();
  return 0;
}

总结:

/*

在c语言中

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

  int f(void);//表示返回值为int的无参函数。

在c++中

  int f(  );和int f(void);具有相同的意义,都表示返回值为int的无参函数。

*/

C++更强调类型,任意的程序元素都必须显示指明类型。

以上(二到六点)都属于语法级别的增强。

七、新增Bool类型关键字

/*

C++中的布尔类型

  c++在c语言的基本类型系统之上增加了bool;

  c++中的bool可取的值只有true和false;

  理论上bool只占用一个字节,如果多个bool变量定义在一起,可能会各站一个bit,这取决于编译器的实现

*/ 

true代表真值,编译器内部用1表示

false代表假值,编译器内部用0表示

boll类型只有true(非0)和false(0)两个值

C++编译器会在赋值时将非0转换为true,0值转换为false。

int main(int argc,char *argv[])
{
  int a;
  bool b=true;
  printf("b=%d,sizeof(b)=%d
",b,sizeof(b));

  b=4;
  a=b;
  printf("a=%d,b=%d
",a,b);
  
  a=10;
  b=a;
  printf("a=%d,b=%d
",a,b);

  b=0;
  printf("b=%d
",b);
  return 0;
}

  

八、三目运算符功能加强

1.三目运算符在c和c++编译器的表现

int  main()
{
  int a=10;
  int b=20;
  //返回一个最小数,并且给最小数赋值成3   //三目运算符是一个表达式,表达式不可能做左值   (a<b?a:b)=30;//这句,c语言中出错,c++中可以给a或者b赋值   //*(a<b?&a:&b)=30//c语言中通过指针可实现同样的效果   printf("a=%d,b=%d ),a,b);   return 0; }

2.结论

(1)c语言返回变量的值,c++语言时返回变量本身

  c语言中的三目运算符返回的时变量值,不能作为左值使用。(表达式的元素结果放在寄存器中,是一个值)

  c++中的三目运算符可以直接返回变量本身,因此可以出现在程序中的任何地方。(表达式的结果放在内存中,返回的是一个内存首地址或指针,是一个变量本身)

(2)注意:三目运算符可能返回的值中如果有一个时常量值,则不能作为左值使用

  如:(a<b?a:b)=30;

(3)c语言如何支持类似c++的特性呢?

  ==>当左值的条件:要有内存空间;c++编译器帮助程序员取了一个地址而已。

          如:*(a<b?&a:&b)=30;

原文地址:https://www.cnblogs.com/cthon/p/9166135.html