【翻译】C++程序员面试题 (1)
原文题目:The Best Questions for Would-be C++ Programmers: Part 1
链接:Topcoder 论坛
原作者 zmij
翻译过程订正了原文一些笔误
引言
在招聘过程中,一个不可缺少而且十分重要的环节是“测试”。“测试”可以为面试官和候选人双方提供信息。面试官可以由此得知候选人的专业能力以及对编程语言的理解;候选人可以得知该工作所需的技术,以及公司期望的技术水平,甚至可以据此决定是否仍想要该职位。
我曾参加过相当数量的面试,或多或少地成功。对那些不得不面对的问题,我愿意分享我的经验。我还向三位高分的topcoder 成员询问反馈。他们是bemerry, kyky 以及sql_lall。他们都十分友善地帮我更正不准确的地方并且贡献了其他的问题。当然,问题的答案可能不是唯一的,不过我尽量把握面试的动态,并让大家仔细思考这些问题。所以,大家拿起铅笔,“一起鉴定潜在的C++程序员以及有潜力的C++程序员”。
1. 什么是类?
类是一种封装数据的方式。该方式在定义抽象数据类型的同时,定义了初始化的条件以及允许的操作。
2.C struct 与 C++ struct的区别?
- C struct 只是将数据组合起来,它只是有特性(数据)而没有包括行为。(函数可以使用结构体但并不是与结构体绑定的)
- Typedef 的别名在C语言中没有自动地为结构体生成,比如:
// a C struct struct my_struct { int someInt; char* someString; }; // 你声明了一个my_struct类型的结构体 struct my_struct someStructure; // 在C语言,你不得不使用typedef来方便地声明变量 typedef my_struct MyStruct; MyStruct someOtherStuct; // a C++ struct struct MyCppStruct { int someInt; char* someString; }; // 声明了 MyCppStruct类型的一个变量 MyCppStruct someCppStruct;
// 由此可以看到该名字被自动typedef
- 最重要的是,C struct并没有提供面向对象概念的实现,比如封装和多态。而且,“C struct不能拥有静态(static)的成员或成员函数”。C++ struct 实际上是class,区别只是在于默认的成员以及基类访问标识符:class默认为private,而struct是public.
3.const关键字的含义,相比#define的优势?
- 简而言之,const意味着只读。一个const声明的,有名字的常量,就像是一个普通的变量,除了它的值不能被修改。任何的数据类型,无论是用户定义或者内置,都可以定义为为const,比如:
-
// myInt变量是一个只读的整形 const int myInt = 26; // 与上一行一样,此处是说明const既可以左结合也可以右结合 int const myInt = 26; // 一个指向常量的指针,不能通过指针修改对象的值,但并不意味所指的是常量 const MyClass* myObject = new MyClass(); // 一个指针常量, 不能指向别的对象,指向的对象本身可以修改 MyClass* const myObject = new MyClass(); // myInt 是一个指向常量的指针常量 const int someInt = 26; const int* const myInt = &someInt;
- #define 容易出错,因为它不像const一样由编译器强制执行。它只是由预处理器进行的替换,并不会有任何的检查。这意味着const关键字会保证类型的正确,而#define不行。使用define而产生的bug会比较难发现,因为它们没有被放在符号表。
- 在C++中,一个常量会有一个作用域,就像一个普通的变量。相反,#define定义的名字是全局有效的,因此可能产生冲突。一个常量必须在声明时定义,即在声明时赋值,而define可以为空。
- 使用const的代码会自然地受到编译器的保护,避免疏忽。比如,对于一个类的状态而言,const成员变量不能被修改,const成员函数不能修改类的成员;对于函数参数而言,const参数的值不能在函数内被修改。最后,编译器的优化对有名字的常量依然有效。
- 总而言之,使用const会比#define有更少的bug和麻烦。
4.解释private, public, 和protected访问控制符?
- public:成员变量和方法可以从类外直接访问。
- private:成员变量和方法不能被类外直接访问。
- protected:成员变量和方法不能直接从类外访问,但子类可以。
- 这些控制符在继承关系中同样被使用,但含义不同,见下一个问题。
5.解释public以及private继承?
- C++中,public继承是最常用的继承机制,通过在基类名字前加上public关键字使用。例子如下:
-
class B : public A { };
- private继承是C++默认的继承方法,如果不声明控制符,将会是私有继承:
-
class B : private A { }; // or class B : A { };
- 在继承语法中,public关键字意味着从基类继承的 公有/私有/保护/ 的成员变量在继承类中依然保持原有的访问控制符。 private关键字意味着所有的基类成员,无论原有的访问控制符是什么,在继承类中都改为私有。
- 使用公有继承,以下的类型转换是允许的。在A等于B的情况,该转换是安全的,但如果B有新的方法,那就是另外的话题了:
-
// B 就是 A
class B : public A {};
A* aPointer = new B();但是,如果使用私有继承,基类的成员在子类当中是私有的,无法被访问:
-
class A { public: A(); ~A(); void doSomething(); }; void A :: doSomething() { } class B : private A { public: B(); ~B(); }; B* beePointer = new B(); // 错误!编译器报错:该方法不可访问 beePointer->doSomething();
// 错误!编译器报错:存在B* 到 A*的类型转换,但是不可访问 A* aPointer = new B();
// 对于以下情形,标准认为是未定义的行为
// 编译器至少对第一个清晰报错:B并不是多态类型
A* aPointer2 = dynamic_cast<A*>(beePointer); A* aPointer3 = reinterpret_cast<A*>(beePointer);
(未完待续)