C++语法-0812

1、using

类型别名:C++11以后,定义类型别名不再是typedef的专利,using也可以用来定义类型别名了,并且可读性更强,using可以像定义一个变量一样来给一个类型取一个别名。

using ULL = unsigned long long; 

别名模板:一族类型的名字,当模板特化时等价于以别名模板的模板实参来替换类型标识中的模板形参的结果。

template 
using vec = vector;
vec v = {0,1,2,3,4,5,6,7,8,9};

2、namespace

命名空间:

  • 防止名字冲突提供的一种控制机制。建立一些互相分隔的作用域,把一些全局实体分隔开来。

  • 命名空间嵌套:在嵌套的命名空间中定义的只能在内层命名空间中有效,外层命名空间想要访问它必须在名字前添加限定符。

  • C++11引入内联命名空间:在namespace前面加上inline关键字,可以直接被外层的命名空间直接使用。

命名别名:当命名空间的名字比较长的时候,给命名空间取一个别名。

#include namespace TestNamespace
{namespace OldNameSpace   // 嵌套命名空间{void myPrintf()  // 全局函数,只是隐藏在指定的命名空间中{cout << "this is OldNameSpace!" << endl;}}namespace OldN = OldNameSpace;  // 取别名inline namespace NewNameSpace{void myPrintf(){cout << "this is NewNameSpace!" << endl;}}
};
namespace TN = TestNamespace;  // 取别名int main()
{using namespace TestNamespace;   // 导入命名空间myPrintf(); 	// 直接调用函数时,调用的是inline声明的命名空间TestNamespace::OldNameSpace::myPrintf(); // C++11之前必须加上命名空间限定符才行TN::OldN::myPrintf();		// 命名别名使用std::cout << "Hello World!\n";getchar();
}

无名命名空间:作用域仅在本文件中(定义的文件),其他文件无法使用。可以用来取代static的作用。

namespace //命名空间没有名字
{void fun( ){ cout<<"OK"<

早期的函数库:

  • 传统C语音的库没有命名空间。
  • C++标准要求系统提供的头文件不包括后缀 .h,都塞进了“std”名字空间中,如iostream、string。C++所用的头文件名是在C语言的相应的头文件名加一个字母c。如stdio.h变成cstdio,string.h变成cstring,math.h变成cmath。注意,C++中cstring和string不是同一个文件,前者提供C语言字符串处理函数(strcmp、strcpy等),后者提供C++字符串处理新功能。

3、string.h cstring string 区别

#include   //不可以定义string s;可以用到strcpy等函数,c版本的头文件
#include    //不可以定义string s;可以用到strcpy等函数,c++版本的头文件,包含命名空间std
#include     //可以定义string s;可以用到strcpy等函数,包含std::string的定义,属于STL范畴

4、typedef用法

1、定义一种类型的别名。不只是简单的宏替换。可以用作同时声明指针型的多个对象。

char* pa, pb; // pa为char*,pb为char
char *pa, *pb; // pa为char*,pb为char*typedef char* PCHAR; // 一般用大写
PCHAR pa, pb;  // pa为char*,pb为char*

2、对古老的C代码,配合struct。

原始:定义时要加struct关键词
struct tagPOINT1 {  int x;   
};  
struct tagPOINT1 p1; 偷懒:
typedef struct tagPOINT {  int x;  
} POINT;  
POINT p1; 

3、定义与平台无关的类型。就是跨平台时,可以只改typedef的值,不用改全部代码。比如std的size_t类型。

4、为复杂的声明定义一个新的简单的别名

原声明:int *(*a[5])(int, char*);  // 变量名为a
简化版:typedef int *(*pFun)(int, char*); pFun a[5];原声明:void (*b[10]) (void (*)()); 	//变量名为b
简化版:typedef void (*pFunParam)();typedef void (*pFunx)(pFunParam);pFunx b[10];原声明:doube(*)() (*e)[9]; 		// 变量名为e, 无参函数的指针,返回值为e的数组指针
简化版:typedef double(*pFuny)();   // 函数指针typedef pFuny (*pFunParamy)[9];   // 数组指针pFunParamy e;右左法则:从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。举例:
eg:int (*func[5])(int *);func 右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明func的元素是指针(注意这里的*不是修饰func,而是修饰 func[5]的,原因是[]运算符优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数组的元素是函数类型的指 针,它指向的函数具有int*类型的形参,返回值类型为int。

5、容易出现的问题

a、typedef是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换

typedef char* PSTR;
int mystrcmp(const PSTR, const PSTR);const PSTR实际上相当于const char*吗?不是的,它实际上相当于char* const。
原因在于const给予了整个指针本身以常量性,也就是形成了常量指针char* const。
记住当const和typedef一起出现时,typedef不会是简单的字符串替换就行。

b、typedef在语法上是一个存储类的关键字(storage class specifier),(如auto、extern、mutable、static、register等一样),虽然它并不真正影响对象的存储特性。

typedef static int INT2; // 错误
typedef register int FAST_COUNTER; // 错误
编译通不过。问题出在你不能在声明中有多个存储类关键字。因为符号 typedef 已经占据了存储类关键字的位置,在 typedef 声明中不能用 register(或任何其它存储类关键字)。

c、typedef 与 #define的区别

1、typedef要比#define要好,#define只是简单的字符串替换#define pStr2 char *;  pStr1 s1, s2;  // s2只是char,而不是char*2、指针常量和常量指针
typedef char * pStr;  
char string[4] = "abc";  
const char *p1 = string;  // 指针常量
p1++;  			// 可以
const pStr p2 = string;  // 常量指针
p2++;  			// 不可以

5、数组和指针

char string[4] = "abc";  
是可以的,而且是常量。
数组只有在初始化可以用=赋值。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部