经典C++笔试题解析1
Sailor_forever sailing_9806@163.com 转载请注明
http://blog.csdn.net/sailor_8318/archive/ 2008/10/29 /3171343.aspx
1、private 与 protect 关键字的区别。
派生类能访问基类的protect成员而不能访问private成员。Private对派生类及用户都不可见,public对派生类和用户都可见,private介于二者之间,对派生类可见对用户不可见。
2、友元,friend 如何声明一个友元。
3、缺省构造函数。当类声明了一个带参数的构造函数后而没有声明无参数构造函数,编译器还会为它生成一个默认的缺省构造函数吗?分析下例的错误:
class A{
public:
A(int i){
cout<<i<<endl;
}
};
void main(){
A a;
}
对于构造函数,为了使编译器自动生成无参构造和拷贝构造函数,你不能定义任何类型的构造函数。
4、构造函数有没有返回值?析构函数有没有返回值?析构函数可不可以带参数?
5、解释一下重载
函数重载允许两个或更多个函数使用同一个名字限制条件是它们的参数表必须不同,即参数类型不同或参数的数目不同。返回值不能作为重载的标志,因为忽略返回值后将无法解析。两个函数只有在相同的作用范围内才能构成重载。
6、重载函数如何来区分彼此?
根据参数个数和类型,C++编译后将生成不同的函数名称,这是C++支持多态的一个特性。
7、解释缺省参数函数
缺省参数允许以不同的形式调用相同的函数,调用时可以省略后续参数,而采用函数声明时的默认值。
8、下例能编译通过吗?为什么。
void s(int i){
cout<<i<<endl;
}
void s(int i, int j=0){
cout<<i<<endl;
}
void main(){
s(5);
}
编译不通过。默认参数和重载函数有时候会产生冲突。重载的缺省参数函数不能与其它函数产生二义。
9、能否用返回值来区分重载函数?
不能,因为大多数时候会忽略返回值,这个时候编译器将无法解析函数调用
10、看下例回答以下问题:
a. 常量必须初始化,下面的代码有何问题:
const int i;
i=20;
有,const常量必须在定义的时候同时初始化,否则就违背了其const的性质
b. 常量有没有存储空间,或者只是编译时的符号而已?
不一定。
在C中,define常量是预处理阶段的工作,其不占据内存。但是const常量总是占据内存
在C++中,const常量是否占据存储空间取决于是否有引用该常量地址的代码。C++对于const默认为内部链接,因此const常量定义通常都放在头文件中,即使分配内存也不会出现链接错误。
若不引用常量对应的地址,则不会为其分配空间。
Const是用来替换define的,因此其必须能够放在头文件中,在C++中const变量是默认为内部链接的,即在其他文件中看不到本文件定义的const变量,因此链接不会出现问题。Const变量在定义的时候必须初始化,除非显式的指定其为extern的。通常C++中会尽量避免为const变量分配内存storage的,而是在编译阶段将其保存在符号表symbol table中。当用extern修饰const变量或引用其地址时,将强制为其分配内存,因为extern表示采用外部链接,因此其必须有某个地址保存其值。
c. 常量一定是在编译时就确定其值的吗?
const int i=100;
const int j=i+100;
long address=(long)&j; //强迫编译器为常量分配存储空间
char buf[j+10];
void main()
{
const char c=cin.get();
const char d=3;
char test1[d+10];
char test2[c+10];
const char c2=c-'a'+'A';
cout<<c<<" "<<c2<<endl;
}
常量不一定是在编译时刻就初始化的。其只是表明只能初始化一次。const char c必须到运行时刻动态获取其初值。char test2[c+10]编译无法通过,因为无法确定c就无法确定数组长度。char buf[j+10];和char test1[d+10];都可以编译通过
单步调试时可以看到j的值,证明为其分配了内存,而无法找到i的符号,因为没有为其分配存储空间。可是为什么可以看到d呢?
11、看下例回答以下问题:
a. 能否将一个非常量对象的地址赋给一个常量指针?
b. 能否将一个常量对象的地址赋给一个非常量指针?若确要如此,该如何做?
可以将非常量对象地址赋值给常量指针,但是不能将常量对象地址给非常量指针,因为其无法保证不修改常量对象。
若却要如此,则只能强制转换,能编译通过,但却可能存在隐患。因此编译器的工作就是将一切可能的隐患扼杀在摇篮中。
void main()
{
const int i=5;
int *j=const_cast<int *>(&i);
}
const int* x; //常量指针
int* const x=&d; //指针常量
int const* x; //常量指针
const int* const x=&d; //常量指针常量
12、函数调用中值传递使用常量定义无意义:
void f(const int i);
但函数返回值的常量定义有特殊作用,看下例:
class X
{
int i;
public:
void modify(){cout<<"haha"<<endl;}
};
const class X fun(){return X();}
void main()
{
//fun().modify(); //常量不能为左值,所以下例也不成立:
//error C2662: 'modify' : cannot convert 'this' pointer from 'const class X' to 'class X &'
const X g = X();
g.modify();
//!!! 常量一定不能为左值吗? 看16题
}
13、常量的典型应用:
void u(const int* p);
const char* v();
14、分析下例说出错误的原因:
class X{};
X f(){return X();}
void g1(X&){}
void g2(const X&){}
void main(){
//! g1(f()); 临时变量都是常量
g2(f());
}
零时变量对用户不可见,因此其为常量,而g1(X&)参数为引用,const实参不能给非const类型新参。若g1采用值传递则没有任何问题
15、如何使用类常量成员,如何初始化?
class Y{
public:
const size;
Y();
};
Y::Y():size(100){}
class X{
enum{i=100};
};