对程序员面试宝典作一些总结--持续更新

再回顾一下,加强一下基础。。

第十章  面向对象

   一、首先梳理一下理论知识

        面向对象技术的基本概念是对象,类和继承。对于一个空类,编译器默认产生4个成员函数:默认构造函数、析构函数、拷贝构造函数和赋值函数。struct和class的区别在于class默认私有,struct默认公有。静态成员是在这个类的所有对象间共享的,设定静态成员变量时,必须赋初值。常量必须在构造函数的初始化列表里面初始化或者设置成static。析构函数可以是内联函数。析构函数可以是虚函数,构造函数不可以。多态的简单概括就是一个接口,多种方法,具体是通过虚函数实现。必须理解重载和覆盖的区别。

  二、 对个别重要的地方深入探讨

      1.认清拷贝构造函数和赋值函数的区别

          拷贝构造函数首先是一个构造函数,它调用的时候产生一个对象,是通过参数传进来的那个对象来初始化,产生的对象。赋值函数是把一个对象赋值给一个原有的对象,所以如果原来的对象中有内存分配要先把内存释放掉,而且还要检查一下两个对象是不是同一个对象,如果是的话就不做任何操作。示例如下:

class A
{
};

int main(void)
{
    A a;
    A aa(a); //拷贝构造函数调用
    A aaa = a;//拷贝构造函数调用
    A b = a;  //赋值函数调用
    return 0;
}

      2.参数为空的构造函数不需要也不能在实例化的时候增加括号。

class Test
{
    Test(int) {}
    Test() {}
    void fun() {}
};

int main(void)
{
    Test a(1);
    a.fun();
    Test b();
    b.fun();
    return 0;
}
编译的时候必然会在b.fun()这一句报错,原因是实例化的对象与函数是有着很大的差别的,不能像调用函数的方法那样实例化对象。所以当参数为空时千万不要加上括号,不然编译器会认为这是声明了一个函数原型,返回值是Test对象。所以下面一句必然出错。

     3.c++类中的常量

          const 数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象其 const 数据成员的值可以不同。所以不能直接在类中初始化常量。如果一定要在类中初始化的话可以增加static关键字,让其在所有实例间共享。

    4.虚析构函数的作用是什么?为什么不有虚构造函数?

         虚析构函数的作用是当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用,否则只有基类的析构函数调用会造成内存泄露。虚拟调用是一种能够在给定信息不完全的情况下工作的机制,对于虚函数,我们仅仅知道它的接口,而不知道具体的对象类型。但是要建立一个对象,你必须拥有完全的信息。特别地,你需要知道要建立的对象的具体类型。因此,对构造函数的调用不可能是虚拟的。 

    5.什么是多态?多态的作用?

         多态可以简单地概括为“一个接口,多种方法”,在程序执行的过程中才决定调用的函数,多态性是面向对象编程领域的核心概念。多态允许将子类类型的指针赋值给父类类型的指针。多态性在C++中是通过虚函数实现的。多态与非多态的区别就是早绑定和晚绑定。至于多态的作用则是实现了接口重用,也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

   6.重载和覆盖的区别

         重载是指编写一个与已有函数同名但是参数表不同的函数。覆盖则是指派生类重写基类的虚函数,重写的函数必须有一致的参数和返回值(c++标准允许返回值不同的情况,但是很少有编译器支持这个特性)。

   7.什么是友元??有什么作用??

        友元是一种定义定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性。友元可以是一个函数,称为友元函数;也可以是一个类,称为友元类。


第十一章  继承与接口

     

   一、首先梳理一下理论知识

        派生类的三种继承方式为公有继承、私有继承和保护继承。虚函数继承与虚继承的区别和各自的作用。多重继承的优缺点。运算符重载与RTTI。

  二、 对个别重要的地方深入探讨

        1.派生类的三种继承方式的区别

          公有继承时,基类的private成员派生类也不可用,基类的public和protected成员在派生类中可直接使用。继承过来(变成派生类相应的public和protected成员)只有public成员在派生类外可以直接使用。

          保护继承时,基类的private成员仍为有私有,基类的public和protected成员变成派生类的protected成员,这时在派生类外也不能直接使用原基类的public成员。

          私有继承时,基类的private成员仍为有私有,基类的public和protected成员将变成派生类的private成员。

        2.虚函数继承和虚继承的区别

           虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也叫动态编联。虚继承是为了在多继承的时候避免引发歧义, 比如类A有个就是a,B继承了A,C也继承了A,当D多继承B,C时,就会有歧义产生了,所以要使用虚拟继承避免重复拷贝。

        3.多重继承的优缺点??

           ① 多重继承本身并没有问题,如果运用得当可以收到事半功倍的效果。②从哲学上来说,C++多重继承必须要存在,这个世界本来就不是单根的。③多重继承在面向对象理论中并非是必要的-----因为它不提供新的语意,可以通过单继承与复合结构来取代。JAVA和C#都放弃了多重继承,使用接口来取代。④多重继承本身并不复杂,对象布局也不混乱,语言中都有明确的定义。真正的复杂的是使用了运行时多态和多重继承。⑤要了解C++,就要明白有很多概念是C++试图考虑但最终放弃的设计。

         4.书中3个小问题

             ①C++中如何阻止一个类被实例化?使用抽象类,或者构造函数声明成private。

             ②一般在什么时候拷贝构造函数被声明成private呢? 比如要阻止编译器生成默认的拷贝构造函数的时候。

             ③什么时候编译器会生成默认的拷贝构造函数呢? 只要自己没写,而程序中需要,都会生成。

         5.RTTI是什么?有什么作用?以及各种强制类型转换符??

             RTTI的重要作用是动态判别执行时期的类型。由于我们软件的设计涉及到类别阶层时,需要判断某个对象所属的累别,而因为程序中类别设计中大量使用了虚函数,所以使得这一工作难以实现但是又极其重要,于是使用了RTTI的typeid运算符能使程序员确定动态对象的动态类型。详细参见我关于RTTI的文章-----------------------------------------

http://blog.csdn.net/u011579318/article/details/37504587

另外引用一下网上看到的14个问题:

1、真正意义上的虚函数调用,是运行时绑定的;
2、什么是真正意义上的虚函数调用?通过指针或者引用执行虚函数;
3、通过对象执行虚函数会不会是动态绑定的?不会。
4、一个类是否有虚函数,就看它是否包含一个指向虚函数表的指针;
5、如果类本身含有virtual 声明的函数,或者继承了virtual 函数,那么它肯定会包含一个指向虚函数表的指针;
6、从纯抽象类或者非抽象类继承了virutal,意义上是一样的,效率上是一样的,并不因为你是纯抽象类的继承而效率变高;
7、虚函数调用比普通函数调用慢多少?假设这个函数仅执行 return i  > j,大概慢 15%左右(3000万 * 100次规模测试),如果是个真正有意义上的函数,效率影响可以忽略不计;
8、因此说虚函数慢的基本上是放屁,担心虚函数影响效率的基本上是杞人忧天;
9、虚函数会慢,但是那是对内联函数而言的,虚函数会忽略 inline前缀,请注意这一点;
10、继承层次不影响虚函数效率,如果你这个类是原始类的第10层继承,那么虚函数调用效率和第1层继承的类没有差别,当然如果你要在该函数中调用上一层的虚函数那就另当别论了;
11、每个类应该只有一个virtual table,而不是每个对象有一个(对象只含有指向虚表的指针),那些说虚函数增大空间开销的可以自宫了;
12、如果一个类含有虚函数,在构造时,使用memset(this, 0, sizeof(*this))是找死的行为;
13、虚函数是运行时多态,模板是编译时多态,一个动,一个是静。
14、子类覆盖父类的虚函数的时候,实际上是在构造函数中修改了虚表中的函数指针;因此使得 FatherClass* p = new ChildClass();的情况下,p->VirtualFunc()始终执行的是子类的虚函数;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值