C/C++知识点整理(3)
2016-03-27 22:38
344 查看
1. C++中构造函数和析构函数可以抛出异常吗?
A.都不行
B.都可以
C.只有构造函数可以
D.只有析构函数可以
答案:C
构造函数尽量不抛异常,析构函数不要抛异常。
对于构造函数:
在构造函数中抛出异常,将导致正在构造的对象的析构函数不会被执行。当对象发生部分构造时,已经构造完成的子对象将被逆序的析构(即异常发生点前面的对象),而还没有开始构造的子对象将不会被构造了(即异常发生点后面的对象),但正在构造的子对象和对象自己本身将停止构建,并且它的析构函数树不会被调用的。
对于析构函数:
more effective c++提出两点理由(析构函数不能抛出异常的理由):
(1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要动作,比如释放某些资源,则这些动作不会被执行,会造成诸如资源泄露的问题。
(2)通常异常发生时,C++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常未处理,又出现新的异常会导致程序崩溃。
解决方案:
如果某个操作可能会抛出异常,class应该提供一个普通函数而非析构函数,来执行该操作。
如果无法保证在析构函数不发生异常。我们可以用try catch来将异常吞下。也就是把异常完全封装在析构函数内部,绝不让异常抛出函数之外。
2. 下面四个类A,B,C,D,在32位机器上sizeof(A),sizeof(B),sizeof(C),sizeof(D)值分别为()
答案: 1,8,1,4
类A空类型的实例虽然不包含任何信息,但是必须在内存中占一定的空间,否则无法使用这些实例,一般都是1。
类B因为内存对齐所以为8。
类C里面虽然有函数,但是只需要知道函数的地址即可,而这些函数的地址只与类型相关,而
与类型的实例无关,编译器不会因为函数而在内存中多添加任何的额外信息.所以还是1 。
类D因为有虚函数,C++的编译器一旦发现一个类型中有虚函数,就会为该类型生成虚函数表,并在该类型的
每一个实例中添加一个指向虚函数表的指针.因为多了一个指针,所以在32位机器为4,64位机器为8。
3. 假定CSomething是一个类,执行下面这些语句之后,内存里创建了__个CSomething对象。
答案:6
CSomething a();// 没有创建对象,这里不是使用默认构造函数,而是定义了一个函数,在C++ Primer393页中有说明。定义一个函数,参数为空,返回值为CSomething对象, 类似int func() 。
CSomething b(2);//使用一个参数的构造函数,创建了一个对象。
CSomething c[3];//使用无参构造函数,创建了3个对象。
CSomething &ra=b;//ra引用b,没有创建新对象。
CSomething d=b;//使用拷贝构造函数,创建了一个新的对象d。
CSomething *pA = c;//创建指针,指向对象c,没有构造新对象。
CSomething *p = new CSomething(4);//新建一个对象。
4. 有以下程序
程序运行后的输出结果是()
A.0123 0173
B.0123 173
C.123 173
D.173 173
答案: C
o% 表示8进制进行输出int m=0123; m已经是8进制不需要进行转换 而n=123是10进制 需要进行8进制转换 得173 。
5. 关于虚函数的描述正确的是()
A.派生类的虚函数与基类的虚函数具有不同的参数个数和类型
B.内联函数不能是虚函数
C.派生类必须重新定义基类的虚函数
D.虚函数可以是一个static型的函数
答案:B
内联函数是编译器就展开的,把代码镶嵌就程序,虚函数是动态绑定,运行期决定的。所以内联函数不能是虚函数 。
6. 有以下程序
程序的输出结果是?
答案:0
这个题目考的是逗号表达式,a = 表达式1,表达式2,则a = 表达式2,同理如果后面有n个表达式的话,返回的是最后一个表达式的值。
7. 有如下程序段:
请问运行Test函数结果是:
A.Thunder Downloader
B.under Downloader
C.Thunderownloader
D.程序崩溃
答案:D
.参数是值传递,函数给参数p重新开辟空间,所以改变的是p指向的空间,str没变。
GetMemory函数执行完成后,str仍然指向NULL,所以赋值时回奔溃 。
正确的做法应该使用双指针 。
8. 不能作为重载函数的调用的依据是:
A.参数个数
B.参数类型
C.函数类型
D.函数名称
答案:C
9.以下代码编译有错误,哪个选项能解决编译错误?
A.改变成员变量”vv”为”mutable int vv”
B.改变成员函数”GetValue”的声明,以使其不是const的
C.都不能修复编译错误
D.都可以修复编译错误
答案:D
mutalbe的中文意思是“可变的,易变的”,跟constant(既 C ++中的const)是反义词。
在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。
10.有一个类B继承自类A,他们数据成员如下:
则构造函数中,成员变量一定要通过初始化列表来初始化的是__。
答案:b,c
在构造函数中需要初始化列表初始化的有如下三种情况 :
1.带有const修饰的类成员 ,如const int a ;
2.引用成员数据,如 int& p;
3.带有引用的类变量
static成员是不允许在类内初始化的,除了const,那么static const 成员是不是在初始化列表中呢?
当然不是。
一是static属于类,它在未实例化的时候就已经存在了,而构造函数的初始化列表嘞,只有在实例化的时候才执行。
其二是static成员不属于对象。我们在调用构造函数是创建对象,一个跟对象没直接关系的成员要它做什么呢 o(^▽^)o。
11. 类A是类B的友元,类C是类A的公有派生类,忽略特殊情况则下列说法正确的是()
A.类B是类A的友元
B.类C不是类B的友元
C.类C是类B的友元
D.类B不是类A的友元
答案:B,D
友元关系是单向的,不是对称,不能传递。
关于传递性,有人比喻:父亲的朋友不一定是儿子的朋友。
那关于对称性,是不是:他把她当朋友,她却不把他当朋友,(●ˇ∀ˇ●)
A.都不行
B.都可以
C.只有构造函数可以
D.只有析构函数可以
答案:C
构造函数尽量不抛异常,析构函数不要抛异常。
对于构造函数:
在构造函数中抛出异常,将导致正在构造的对象的析构函数不会被执行。当对象发生部分构造时,已经构造完成的子对象将被逆序的析构(即异常发生点前面的对象),而还没有开始构造的子对象将不会被构造了(即异常发生点后面的对象),但正在构造的子对象和对象自己本身将停止构建,并且它的析构函数树不会被调用的。
对于析构函数:
more effective c++提出两点理由(析构函数不能抛出异常的理由):
(1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要动作,比如释放某些资源,则这些动作不会被执行,会造成诸如资源泄露的问题。
(2)通常异常发生时,C++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常未处理,又出现新的异常会导致程序崩溃。
解决方案:
如果某个操作可能会抛出异常,class应该提供一个普通函数而非析构函数,来执行该操作。
如果无法保证在析构函数不发生异常。我们可以用try catch来将异常吞下。也就是把异常完全封装在析构函数内部,绝不让异常抛出函数之外。
~ClassName() { try{ do_something(); } catch(){ //可以什么都不做,只是保证catch块的程序抛出的异常不会被扔出析构函数之外 } }
2. 下面四个类A,B,C,D,在32位机器上sizeof(A),sizeof(B),sizeof(C),sizeof(D)值分别为()
class A{ }; class B{ char ch; int x; }; class C{ public: void Print(void){} }; class D { public: virtual void Print(void){} };
答案: 1,8,1,4
类A空类型的实例虽然不包含任何信息,但是必须在内存中占一定的空间,否则无法使用这些实例,一般都是1。
类B因为内存对齐所以为8。
类C里面虽然有函数,但是只需要知道函数的地址即可,而这些函数的地址只与类型相关,而
与类型的实例无关,编译器不会因为函数而在内存中多添加任何的额外信息.所以还是1 。
类D因为有虚函数,C++的编译器一旦发现一个类型中有虚函数,就会为该类型生成虚函数表,并在该类型的
每一个实例中添加一个指向虚函数表的指针.因为多了一个指针,所以在32位机器为4,64位机器为8。
3. 假定CSomething是一个类,执行下面这些语句之后,内存里创建了__个CSomething对象。
CSomething a(); CSomething b(2); CSomething c[3]; CSomething &ra = b; CSomething d=b; CSomething *pA = c; CSomething *p = new CSomething(4);
答案:6
CSomething a();// 没有创建对象,这里不是使用默认构造函数,而是定义了一个函数,在C++ Primer393页中有说明。定义一个函数,参数为空,返回值为CSomething对象, 类似int func() 。
CSomething b(2);//使用一个参数的构造函数,创建了一个对象。
CSomething c[3];//使用无参构造函数,创建了3个对象。
CSomething &ra=b;//ra引用b,没有创建新对象。
CSomething d=b;//使用拷贝构造函数,创建了一个新的对象d。
CSomething *pA = c;//创建指针,指向对象c,没有构造新对象。
CSomething *p = new CSomething(4);//新建一个对象。
4. 有以下程序
#include<iostream> #include<stdio.h> using namespace std; int main(){ int m=0123, n = 123; printf("%o %o\n", m, n); return 0; }
程序运行后的输出结果是()
A.0123 0173
B.0123 173
C.123 173
D.173 173
答案: C
o% 表示8进制进行输出int m=0123; m已经是8进制不需要进行转换 而n=123是10进制 需要进行8进制转换 得173 。
5. 关于虚函数的描述正确的是()
A.派生类的虚函数与基类的虚函数具有不同的参数个数和类型
B.内联函数不能是虚函数
C.派生类必须重新定义基类的虚函数
D.虚函数可以是一个static型的函数
答案:B
内联函数是编译器就展开的,把代码镶嵌就程序,虚函数是动态绑定,运行期决定的。所以内联函数不能是虚函数 。
6. 有以下程序
#include <stdio. h> int fun( intA ) { int b = 0; static int c = 3; a = ( c + +,b + + ); return ( a ); } main( ) { int a = 2,i,k; for( i = 0;i<2;i + + ) k = fun( a + + ); printf("%d\n",k ); }
程序的输出结果是?
答案:0
这个题目考的是逗号表达式,a = 表达式1,表达式2,则a = 表达式2,同理如果后面有n个表达式的话,返回的是最后一个表达式的值。
7. 有如下程序段:
#include <iostream> void GetMemeory(char *p) { p = (char *)malloc(100); } void Test() { char *str = NULL; GetMemeory(str); strcpy(str, "Thunder"); strcat(str + 2, "Downloader"); printf(str); }
请问运行Test函数结果是:
A.Thunder Downloader
B.under Downloader
C.Thunderownloader
D.程序崩溃
答案:D
.参数是值传递,函数给参数p重新开辟空间,所以改变的是p指向的空间,str没变。
GetMemory函数执行完成后,str仍然指向NULL,所以赋值时回奔溃 。
正确的做法应该使用双指针 。
void GetMemory(char **p){ *p = (char *)malloc(100); } void Test(){ char *str = NULL; GetMemory(&str); printf(str); }
8. 不能作为重载函数的调用的依据是:
A.参数个数
B.参数类型
C.函数类型
D.函数名称
答案:C
9.以下代码编译有错误,哪个选项能解决编译错误?
class A { public: int GetValue() const { vv = 1; return vv; } private: int vv; };
A.改变成员变量”vv”为”mutable int vv”
B.改变成员函数”GetValue”的声明,以使其不是const的
C.都不能修复编译错误
D.都可以修复编译错误
答案:D
mutalbe的中文意思是“可变的,易变的”,跟constant(既 C ++中的const)是反义词。
在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mutalbe来修饰。
10.有一个类B继承自类A,他们数据成员如下:
class A { ... private: int &a; }; class B : public A { ... private: int a; public: const int b; A c; static const char* d; A* e; };
则构造函数中,成员变量一定要通过初始化列表来初始化的是__。
答案:b,c
在构造函数中需要初始化列表初始化的有如下三种情况 :
1.带有const修饰的类成员 ,如const int a ;
2.引用成员数据,如 int& p;
3.带有引用的类变量
static成员是不允许在类内初始化的,除了const,那么static const 成员是不是在初始化列表中呢?
当然不是。
一是static属于类,它在未实例化的时候就已经存在了,而构造函数的初始化列表嘞,只有在实例化的时候才执行。
其二是static成员不属于对象。我们在调用构造函数是创建对象,一个跟对象没直接关系的成员要它做什么呢 o(^▽^)o。
11. 类A是类B的友元,类C是类A的公有派生类,忽略特殊情况则下列说法正确的是()
A.类B是类A的友元
B.类C不是类B的友元
C.类C是类B的友元
D.类B不是类A的友元
答案:B,D
友元关系是单向的,不是对称,不能传递。
关于传递性,有人比喻:父亲的朋友不一定是儿子的朋友。
那关于对称性,是不是:他把她当朋友,她却不把他当朋友,(●ˇ∀ˇ●)
相关文章推荐
- 关于C/C++一些面试/笔试题的反思(超基础的知识点)
- 如何避免内存泄漏
- 副本构造器
- gets和scanf函数初篇
- c语言实现des加密
- c++实验2—标准体重
- 关于C++中delete和delete[]的差别
- 表面静如处子其实动如脱兔的static
- C++第二次上机实验-3
- c++实验2-标准体重
- 想找C++开发职位必读的书,以及其他条件
- C++学习笔记55——类模板的输入输出操作符
- c语言:顺序栈的实现
- C++面向对象和流
- 九月十月百度人搜,阿里巴巴,腾讯华为笔试面试八十题(第331-410题) C++版
- C++ const的各种用法
- C++设计模式之适配器(Adapter)模式
- Java客户端与C++服务器端通信
- 2014秋C++第5周项目1參考-见识刚開始学习的人常见错误
- 一个简单的程序教你区分C++中strlen与sizeof