面试题--C++基础篇(补充)

const用法

1)定义一个常量,可以很方便地进行参数的调整和修改。const对象一旦创建后其值不能被修改,所以const对象必须初始化。

2const变量相对于宏定义更安全。编译器可以对const变量进行类型安全检查,而对宏定义只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。

3)可以保护被修饰的东西,防止被意外修改,增强程序的健壮性。如:void fun(const string& str)

4)为函数重载提供了一个参考

struct A
{
void fun(void) {cout<<”void fun(void)”<<endl;}       //一个函数
void fun(void) const { cout<<”void fun(void)const”<<endl;}  //上一个函数的重载
};
A a1;const A a2;
a1.fun();  // void fun(void)
a2.fun();  // void fun(void) const

5)可以节省空间,避免不必要的内存分配。const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数。所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

const inti = 0;        //此时不会分配空间
int *j =(int *) &i;      //分配空间
*j = 1;
printf("%d,%d", i, *j);  //   0, 1   原因:i在编译时直接被替换,指针j指向分配的空间

6const的引用

a)        对常量的引用(reference to const),简称常量引用。对常量的引用不能被用作修改它所绑定的对象

const int ci = 1024;          const int &r1 = c1;

b)       对const的引用可能引用一个非cconst的对象

常量引用仅对引用可参与的操作做出限定,对于引用的对象本身是不是一个常量未作限定。因为对象也可能是个非常量,所以允许通过其他途径改变它的值。

int i = 42; cons tint &r2= i;

7)指针和const

a)        指向常量的指针(pointer to const):不能用于改变其指向的值。要想存放常量对象的地址,只能使用指向常量的指针:

const int pi = 10;      cons tint *cptr = pi; //允许不赋初始值

和常量引用一样,指向常量的指针也没有规定其所指向的对象必须是一个常量。

b)        const指针(常量指针 const pointer):必须初始化,一旦初始化,其值不能在改变。

int num = 10;             int *const pNum = &num;

指针本身是一个常量并不意味着不能通过指针修改其所指对象的值,能否这样做完全依赖于所指向的对象。

扩展:顶层const(top-level-const)和底层cosnt(low-level-const)

顶层const:表示指针本身是个常量;低层cosnt:表示指针所指的对象是一个常量。

顶层cosnt可以表示任意的对象是常量,对任何数据类型都适用,如算数类型、类和指针等。

底层const则与指针和引用等复合类型的基本类型部分有关。

int i =0;            
int*const p1 = &i;        //不能改变p1的值,顶层const
const intci = 42;         //不能改变ci的值,顶层const
cons tint*p2 = &ci;       //允许改变p2的值,底层const
const int*const p3 = p2;  //靠右的const是顶层const,靠左的const是底层cosnt
const int&r = ci;         //用于声明引用的const都是底层const

1)当执行对象拷贝时,常量是底层const和顶层const区别明显。其中,顶层const不受影响:

i = ci;     //正确:拷贝ci的值是一个顶层const,对此操作无影响

P2 =p3;   //正确:p2和p3指向的对象类型相同,p3顶层const的部分不影响

2)底层的const的限制却不能忽视。当执行对象的拷贝时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说,非常量可以转换成常量,反之则不行:

int *p =p3;        //错误:p3包含底层const的定义,而p没有
p2 = p3;           //正确:p2和p3都是底层const
p2 =&i;            //正确:int*能转换成const int*
int&r = ci;        //错误:普通的int&不能绑定到int 常量上
const int&r2 = i;  //正确:const int&可以绑定到一个普通int上

C++中四种类型转换方式

1)        static_cast任何具有明确定义的类型转换,只要不包括底层const,都可以使用static-cast。主要用于基本类型间的相互转换,和具有继承关系间的类型转换(将子类类型的指针转换为父类类型的指针,也能够转换父类类型的指针为它的子类类型的指针)。

a) 当把一个较大的算数类型赋值给较小类型时,static_cast非常有用。

double i = 10.3;                  int num =static_cast<int>(i);

b) 对于编译器无法自动执行的类型转换也非常有用。

int d = 10;        void*p = &d;           int *dp =static_cast<int*>(p);

2)        const_cast只能改变运算对象的底层const

const char *pc;

char *p =const_cast<char*>(pc);  //正确:但通过p写值是未定义的行为

对于将常量对象转换为非常量对象的行为,称其为“去掉const性质(cast away the const)”。一旦去掉某个对象的const性质,编译器就不再阻止我们对该对象进行写操作了。如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的;然而如果对象是一个常量,在使用const_cast执行写操作就会产生未定义的后果。

const_cast常常用于由函数重载的上下文中。

3)        reinterpret_cast通常为对象的位模式提供较低层次上的重新解释。将一个类型的指针转换为另一个类型的指针,它也允许从一个指针转换为整数类型。这种转换不用修改指针变量值数据存放格式(不改变指针变量),而是在编译时重新解释指针的类型(操作结果只是简单的从一个指针到别的指针的值的二进制拷贝。在类型之间指向的内容不做任何类型的检查和转换)。但不能用于非指针类型的转换。

4)        dynamic_cast只能在继承类对象的指针之间或引用的相互转换,且通常情况下应含有虚函数,在运行时动态转换。只用于对象的指针和引用。当用于多态类型时,它允许任意的隐式类型转换以及相反过程,会检查操作是否有效。指针间转换失败可以通过判断是否为null来判断,引用转换失败则抛出 bad_cast 异常。

注:当知道派生类的具体类别时,使用static_cast效率更高。

静态成员变量、非静态成员变量,静态方法和非静态方法的区别

1)静态成员变量:在C++中,静态成员变量是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。静态成员变量使用前必须先初始化。

2)非静态成员变量:不可以直接使用类名访问,可以用实例化来访问,每个对象均有一份独立的值。

3)静态成员函数中不能调用非静态成员,只能调用静态成员变量。

4)非静态成员函数中可以调用静态成员。因为静态成员属于类本身,在类的对象创建之前就已经存在了,所以在非静态成员函数中是可以调用静态成员的。

静态成员可以通过双冒号来使用即<类名>::<静态成员名>

class A
{
public:
	static int num;
	int data;
	A(int i=0):data(i){++num; ++data;}
	static int getNum(){return num;}
};
int A::num = 0;
int main(void)
{
	A a;
	cout<<"A::num="<<A::getNum()<<" data="<<a.data<<endl; //A::num=1 data = 1;
	A b;
	cout<<"A::num="<<A::getNum()<<" data="<<a.data<<endl; //A::num=2 data = 1;
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值