面试题1:下面那个const应该被移除?
代码如下:
const bufsize = 100;
#include<windows.h>
#include<iostream>
#include BUF_SIZE 30
using namespace std;
class A
{
public:
A();
~A(){};
public:
intlie const[A] BYTE * GetBuffer() const[B]//这样的函数是常成员函数,只读函数,它既不能更改数据成员的值,也不能调用那些能引起数据成员值变化的成员函数,只能调用
//const成员函数
{reurn m_pBuf;}
private:
const[C] BYTE* const[D] m_pBuf;
};
A::A():m_pBuf()
{ BYTE* pBuf = new BYTE[BUF_SIZE
if(p_Buf ==NULL)
return;
for(int i = 0;i<BUF_SIZE;++i)
{ pBuf[i]= i}
m_pBuf=pBuf;
}
int main()
{
}
解析:关于const修饰指针的情况,一般分为如下4中情况:
int b =500;
const int * a =&b;//情况1
int const*a =&b;//情况2
int *const a =&b;//情况3
const int* const a =&b;//情况4
如何区别呢?
1.先看情况1
如果const位于星号的左侧,则const就是用来修饰指针所指的变量,即指针指向常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此指针情况1和2是一样的,都是指针所指向的内容为常量,(const放在变量声明符的位置无关),这种情况下不允许对内容进行更爱操作。
对于情况1,可以先不进行初始化。因为虽然指针内容是常量,但指针本身不是常量。
2.情况3为指针本身是常量,这种情况下不能对指针本身进行更改,而指针所指向的内容不是常量。
定义时必须同时初始化
3.对于情况4为指针本身和指向的内容均为常量。
下面我们在说一下const成员函数是什么?
我们定义的类的成员函数中,常常有一些成员函数不改变类的数据成员,也就是说这些函数是只读函数。而有些函数要修改类数据成员的值。如果把不改变数据的函数都加上const关键字进行标识,显然,可提高程序的可读性。其实它还能提高程序的可靠性,已经定义成const的成员函数,一旦企图修改数据的值,则编译器按错误处理。
答案:D ,因为如果存在const BYTE* const m_pBuf;的情况,势必要进行初始化。
面试题2: const与#define相比有什么不同?
答案:C++语言可以用const定义常量,也可以用#define定义常量,但前者比后者有跟多的优点。
const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而后者只进行字符替换,没有类型安全检查,并且字符替换可能会产生意想不到的错误(边际效应)
有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试,在C++程序中只使用const常量而不是用宏常量,即const常量完全取代宏常量。
C++中默认const是内部连接的,这样如果在C++中想完成与C中同样的事情,必须用exteren把内部连接改成外部连接
面试题3:有类如下:
Class A
{void F()const
}
在上面这种情况下,如果要修改类成员变量,应该怎么办?
解析:在C++程序中,类里面的数据成员加上muable后,修饰为const的成员函数就可以进行修改了。代码如下:
#include<iostream>
#include<iomanip>
using namespace std;
class C
{
public:
C(int i):m_Count(i){}
int incr() const
//注意这里的const
{
return ++m_Count;
}
int decr() const
{
return --m_Count;
}
private:
mutable int m_Count;
//可以将这里的mutable去掉再编译试一试
};
int main()
{
C c1(0),c2(10);
for(int tmp,i =0;i<10;++i)
{cout<<setw(tmp)<<setfill(' ')
<<tmp<<endl;
tmp = c2.decr();
cout<<setw(tmp)<<setfill(' ')
<<tmp<<endl;
}
return 0;
}
答案: 在const成员函数中,用mutable修饰成员变量名后,就可以类的成员的变量了