C++面试题
1. 指针和引用的差别?
答:
- 非空区别: 在任何情况下都不能使用指向空值的引用. 一个引用必须总是指向某些对象. 因此如果使用一个变量并让他指向一个对象, 但是该变量在某些时候也可能不指向任何对象, 这时应该把变量声明为指针, 因为这样可以赋空值给变量. 相反, 如果变量肯定指向一个对象, 例如你的设计不允许变量为空, 这时就可以把变量声明为引用. 不存在指向空值的引用这个事实意味着使用引用的代码效率会比使用指针要高.
- 合法性区别: 在使用引用之前不需要测试它的合法性. 相反, 指针则应该总是被测试, 防止其为空
- 可修改区别: 指针与引用的另一个重要的区别是指针可以被重新赋值以指向另一个不同的对象. 但是引用总是指向在它初始化时被指定的对象, 以后不能改变, 但是指定的对象其内容可以改变.
- 应用区别: 总的来说, 在以下情况下应该使用指针:
- 考虑到存在不指向任何对象的可能(这种情况下,可以设置指针为空)
- 需要能够在不同的时刻指向不同的对象(这种情况下能改变指针的指向)
如果总是指向一个对象并且一旦指向一个对象后就不会改变指向, 那么应该使用引用.
2. 哪一种成员变量可以在同一个类的实例之间共享?
答: 必须使用静态成员变量在一个类的所有实例间共享数据. 如果想限制对静态成员变量的访问, 则必须把它们声明为保护型或私有型. 不允许用静态成员变量去存放某一个对象的数据. 静态成员数据是在这个类的所有对象间共享的,
3. 常量必须在构造函数的初始化列表里面初始化或者将其设置成static.
4. 析构函数可以为virtual型, 构造函数则不能, 那么为什么构造函数不能为虚呢?
答: 虚函数采用一种虚调用的方法. 虚调用是一种可以在只有部分信息的情况下工作的机制, 特别允许我们调用一个只知道接口而不知道其准确对象类型的函数. 但是如果要创建一个对象, 你势必要知道对象的准确类型, 因此构造函数不能为虚.
5. 析构函数可以是内联函数吗?
答: 可以先构造一个类, 让它的西沟函数是内联函数. 所以析构函数可以是内联函数.
6. 什么是多态?
答: 多态性可以简单概括为" 一个接口, 多种方法". 在程序运行的过程中才决定调用的函数. 多态性是面向对象编程的核心概念.
多态, 按字面意思就是"多种形状", 多态性是运行你将父对象设置成为和它的一个或更多的子对象相等的技术, 赋值之后, 父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作. 简单地说就是一句话: 允许将子类类型的指针赋值给父类类型的指针. 多态性在object pascal和c++中都是通过虚函数实现的.
7. 什么是虚函数?
答: 虚函数就是允许被其子类重新定义的成员函数. 而子类重新定义父类虚元素的做法, 被成为"覆盖" 或者成为"重写".
8. 重写和重载的区别?
答:覆盖(重写)指子类重新定义父类的虚函数的做法, 即虚函数总是在派生类中被改写. 而重载, 是指允许存在多个同名函数, 而这些函数的参数表不同(或参数个数不同, 或参数类型不同, 或两者都不同).
重载和多态无关. 真正和多态相关的是覆盖. 当子类重新定义了父类的虚函数后, 父类指针根据赋给它的不同的子类指针, 动态地调用属于子类的该函数, 这样函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出). 因此, 这样的函数地址是在运行期绑定的(晚绑定). 所以重载只是一种语言特性, 与多态无关, 与面向对象也无关.
9. 多态的作用
封装可以隐藏实现细节, 使得代码模块化;
继承可以扩展已存在的代码模块(类), 它们的目的都是为了代码重用.
而多态则是为了实现接口重用.
10. 宏, 内联函数, 模板都可以在编译时候解析, 唯独虚函数必须在运行时才能确定.
11. 友元:
友元函数或友元类. 是一种定义在类外部的普通函数, 但是需要在类体内进行说明, 为了与该类的成员函数加以区别, 在说明时前面加以关键字friend. 友元不是成员函数, 但是它可以访问类中的私有成员.
友元的作用在于可以提高程序的运行效率, 但是, 它破坏了类的封装性和隐藏性, 使得非成员函数可以访问类的私有成员.
12. 派生类的3种继承方式:
答:
- 公有继承(public)
- 基类成员对其对象的可见性与一般类及其对象的可见性相同, 公有成员可见, 其他成员不可见. 这里保护成员与私有成员相同
- 基类成员对派生类的可见性对派生类来说, 基类的公有成员和保护成员可见, 基类的公有成员和保护成员作为派生类的成员时, 它们都保持原有的状态; 基类的私有成员不可见, 基类的私有成员仍然是私有的, 派生类不可访问基类中的私有成员
- 基类成员对派生类对象的可见性对派生类来说, 基类的公有成员是可见的, 其他成员是不可见的.
- 所以,在公有继承时, 派生类的对象可以访问基类中的公有成员, 派生类的成员函数可以访问基类中的公有成员和保护成员
13. 什么是虚继承? 它与一般的继承有什么不同? 它有什么用?
答: 虚继承是多重继承中特有的概念. 虚拟基类是为了解决多重继承而出现的.
14. 什么是虚指针?
答: 虚指针或虚函数指针是一个虚函数的实现细节. 带有虚函数的类中的每一个对象都有一个虚指针指向该类的虚函数表.
15. C++中如何阻止一个类被实例化?
答: 使用抽象类, 或者构造函数被声明为private
16. 构造函数被声明成private会阻止编译器生成默认的copy constructor吗?
答: 构造函数设为private, 并不能阻止编译器生成默认的copy constructor, 这是毫不相干的两件事情. 如果我们没有定义复制构造函数, 编译器就会为我们合成一个. 与默认构造函数不同, 即使我们定义了其他构造函数, 也会合成复制构造函数.
- 私有继承(private)
- 保护继承(protected)
char * Getmemory(void) { char p[] = "hello world!"; return p; } void test() { char *str = NULL; str = Getmemory(); printf("%s",&str); }