【翻译】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);

     

 (未完待续)

posted on 2017-06-04 22:08  Kinsang  阅读(1777)  评论(0编辑  收藏  举报

导航