sailing

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  1 Posts :: 4 Stories :: 0 Comments :: 0 Trackbacks

常用链接

留言簿(10)

我参与的团队

搜索

  •  

最新评论

2009年10月24日 #



4、下面类的两种不同的构造函数的区别 
   
 Sample::Sample(string name):_name(name){} 
 Sample::Sample(
string name){_name=name;} 
解答:
line1是构造函数初始化列表初始化,line2是构造函数体内对成员赋值。
初始化列表初始化 和 构造函数体内初始化的区别主要是在与数据成员的类型。
       从概念上讲,可以认为构造函数分两个阶段执行:(1)初始化阶段;(2)普通的计算阶段。
计算阶段由构造函数体内的所有语句完成。
       没有在构造函数初始化列表里初始化的成员,使用与初始化变量同样的规则进行初始化。
运行该类型的默认构造函数来初始化类类型的数据成员。局部作用域的内置类型成员不被初始化,
全局作用域的成员初始化为0.
        有三种成员必须在初始化列表中初始化:没有默认构造函数的类类型成员、const成员、引用类型成员。

     
5、类继承后成员变量的可见性(三种类型的变量及public, private类型的继承)
 public继承:public >> public,  protected>>protected,  private >> private
protected继承:public,protected >> protected,     private>>private
private继承: all  >> private.


7、空类的系统自动产生的函数(至少写4个)
    class Sample
{    };

C++中的空类,默认产生的类成员函数:  
class   Empty
{   
      
public:   
          Empty();                                                   
//   缺省构造函数   
          Empty(const   Empty&);                           //   拷贝构造函数   
          ~Empty();                                                 //   析构函数   
          Empty&   operator=(const   Empty&);     //   赋值运算符   
          Empty*   operator&();                             //   取值运算符   
          const   Empty*   operator&()   const;     //   取值运算符const   
};


8、2 write the output

#include <iostream>
#include 
<string>
using namespace std;
void println(const std::string& msg)
{
std:cout
<<msg<<’\n’;
}
class Base{
public:
         Base() {println(“Base::Base()”);virt();}
         void f(){println(“Base::f()”);virt();}
         virtual 
void virt(){println(“Base()::virt()”);}
};
class Derived:public Base
{
         Derived(){println(“Derived:: Derived ()”);Virt();}
         Virtual 
void virt(){println(“Derived ()::virt()”);}
};
int main(int argc,char* argv[])
{
         Derived d;
         Base 
*pB=&d;
         PB
->f();
}

8.1 (5%) what is the output of the code “pB->f();” above?
8.2 (5%) what is the output of the code “Dervied d;” above?

解答:
8.1:基类类型的指针pBase指向派生类对象,pBase调用基类的非虚函数 f( ) 时,
         如果该非虚函数中又调用了虚函数 vf( )。那么调用的 vf() 版本是派生类里的 vf( ) . 
         其实也很好理解,被调函数A里嵌入的函数B也是由A的主调者调用。 
         侯捷深入浅出MFC里64页有这么一句话:“ 每一个 '内含虚函数的类 ',编译器都
          会为它做出一个虚函数表,表中的每一个元素都指向一个虚函数的地址。此外
          编译器也会为类加上一项成员变量,是一个指向虚函数表的指针(常被称为 vptr)
          .....实际上,每一个由此类派生出来的对象,都有这么一个vptr,当我们通过这个对象
          调用虚函数时,事实上是通过vptr找到虚函数表,再找出虚函数的真正地址。”
           看一个例子:
class CBase
{
public:
    
virtual void vf()
    {
        cout
<<"CBase"<<endl;
    }
    
int a;

};


void main()
{
    CBase obj;
    
sizeof(obj)==8;
//  如果去掉类中的virtual关键词,则sizeof(obj)==4。
//可见,每个由内含虚函数的类派生的对象都含一个vptr.


}
            

8.2. 实际上当构造函数已经执行到内部的语句时,这个对象已经构造出来了。
       那么构造函数内部调用其他的成员函数,就是通过这个刚刚构造出来的对象
       调用的。 
       因此,本例中Drived d;构造过程中,先调用基类的构造函数构造基类部分,
       再调用派生类的构造函数构造派生类独有部分。当派生类的构造函数执行到
        构造函数体内的时候,该对象已经完全构造出来了,那么派生类构造函数中
        的函数调用是由刚刚构造出的这个对象调用的。因此virt()是由这个新对象的
         隐含的vptr调用的派生类版本virt()。




posted @ 2009-10-24 00:26 sailing 阅读(1416) | 评论 (0)编辑 收藏