一、指针常量 & 常量指针
(1)、有以下定义,说明哪些量可以改变哪些不可以改变
const char *p; *P不改变,P可以改变
const (char *) p; *P不改变,P可以改变
char *const p; 报错
const char* const p; P和*P不改变
char const *p; *P不能被改变,P可以改变
(char *) const p; 报错
char const* const p; *P和P不改变
- const char *p:指向字符常量的指针,可更改指针以修改
p
自身以指向不同的数据(地址),不能通过p
修改它所指向的内容。- const (char *) p:指向字符常量的指针,可更改指针本身,但不能更改所指向的字符内容。
- char *const p:报错,通常情况下const放在*之前,而并非放在指针变量
p
之后。- const char* const p:指向字符常量的常量指针,不可更改指针以修改
p
自身以指向不同的数据(地址),不能通过p
修改它所指向的内容。- char const *p;:指向字符常量的指针,类似于第一种情况。也就是说,可更改指针以修改
p
自身以指向不同的数据(地址),但不能更改p
自身所指向的字符内容。- (char *) const p:报错,通常情况下const放在*之前,而并非放在指针变量P之后。
- char const* const p:指向字符常量的常量指针,既不能通过
p
指针更改指向地址,也不能改变p
所指向的字符内容。此处const修饰符的顺序可以稍作修改,如const (char const*) p。
二、C++中":"和"::"区别
(1)、单引号:
1.继承
class 派生类名 :继承方式 基类名
#include <iostream>
using namespace std;
class BaseClass
{
public :
BaseClass();// 构造函数
~BaseClass();// 析构函数
}
class SubClass:public BaseClass()
{
}
2.初始化参数
初始化类的成员两种方式:
一、是使用初始化列表
二、是在构造函数体内进行赋值操作
2.1初始化参数原因
原因:主要是出于性能问题,对于内置数据类型:如int, double等,使用初始化列表和在构造函数体内初始化差别不是很大,但是对于类类型来说,最好使用初始化列表。因为使用初始化列表少了一次调用默认构造函数的过程,这对于数据密集型的类来说,非常高效
所以一个好的原则是,能使用初始化列表的时候尽量使用初始化列表
2.2成员变量顺序
成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的。
3. 位域
该种形式出现于结构体或共用体的定义中,是位域定义的标准形式。
struct BaseClass
{
type var_name : m;
};
- 含义为,在结构体BaseClass汇总,成员变量var_name占用空间为m位。
- m为正整数,其值必须小于type类型占用的位数。比如type如果是int,占4字节32位,那么m必须是1~31之间的整数。
- 对于位域类型的成员,在赋值时如果实际值超过n位所能表达的范围,那么超出部分将会被截掉,只保存低位值。例:int var:4,本身只有4位的空间,如果赋值var = 20, 由于20的二进制值为10100,实际为五位,这时var实际被赋值的就是低四位,0100,即4。
(2)、双引号::
1. 类作用域,用来标明类的变量、函数
作用域符号::的前面一般是类名称,后面一般是该类的成员名称,C++为例避免不同的类有名称相同的成员而采用作用域的方式进行区分
Human::SetName(char* name);
2. 命名空间作用域,用来注明所使用的类、函数属于哪一个命名空间
std::cout << "Hello World" << std::endl;
3. 全局作用域,用来区分局部、全局
全局作用域符号:当全局变量在局部函数中与其中某个变量重名,那么就可以用::来区分如:
char base; //全局变量
void Init()
{
char base; //局部变量
char(局部变量) = char(局部变量) *char(局部变量) ;
::char(全局变量) =::char(全局变量) *char(局部变量);
}
一般写了一个全局函数或者想要调用一个全局函数,却发现IDE或者Editor找不到该函数,原因是因为局部函数与想要调用的全局函数名字重合,然后找了很久也找不到原因,甚至放弃解决的。其实原因就是因为 【局部变量/函数】 与 【全局变量/函数】 的名字相同,IDE无法区分,这时候加上 :: 就可以调用到全局函数,访问到全局变量。
示例:
.h文件下打开、关闭函数api接口
//.h文件下的全局函数
File* open (const char *p, int flag)
//.h文件下的全局函数
extern int close (int fd);
由于每次找api是一件非常浪费加载时间,而且是没多大意义的事情,我现在要将这个函数封装成个人串口库base.cpp
//Base.h
class Base
{
public:
bool open();
void close();
}
注意以下的cpp文件,如果没有 :: 则会报错误,因为Base库中有函数open和close,跟全局函数open和close名字相同,如果不做全局与局部的区分,则无法调用到全局函数
// Base.cpp
bool Base::open()
{
if( ::open(portname,O_RDWR|O_NOCTTY|O_NONBLOCK) != -1 )
return true;
else
return false;
}
void Base::close()
{
::close(fd);
}
三、总结命名空间使用时的方式和注意事项
- 多个空间变量冲突时,要使用域限定符,来标识一个命名空间;
- 本地群居和局部冲突,本地全局变量使用::变量名的引用,因为本地全局变量保存在匿名空间内;
- 在命名空间内定义函数,需要给函数加上域限定符和命名空间
- 嵌套命名空间,需要一级一级引用