一公司笔试题

楼主pbcd(沙漠绿州)2005-12-22 17:58:09 在 C/C++ / 新手乐园 提问

1. 请仔细阅读下面的资料:  
    材料一:CArray  
  template<   class   TYPE,   class   ARG_TYPE   >   class   CArray   :   public   CObject  
  Parameters:  
  TYPE  
  Template   parameter   specifying   the   type   of   objects   stored   in   the   array.    
  TYPE   is   a     parameter   that   is   returned   by   CArray.  
  ARG_TYPE  
  Template   parameter   specifying   the   argument   type   used   to   access   objects   stored   in   the     array.    
   
  Often   a   reference   to   TYPE.   ARG_TYPE   is   a   parameter   that   is   passed   to   CArray.  
   
  Remarks:  
  The   CArray   class   supports   arrays   that   are   are   similar   to   C   arrays,   but   can   dynamically     shrink   and   grow   as   necessary.    
   
  Array   indexes   always   start   at   position   0.   You   can   decide   whether   to   fix   the   upper   bound   or   allow   the   array   to   expand   when   you   add   elements   past   the   current   bound.   Memory   is   allocated   contiguously   to   the   upper   bound,   even   if   some   elements   are   null.  
     
  int   CArray::Add   (ARG_TYPE   newElement);  
     
  Return   Value:  
  The   index   of   the   added   element.  
  Parameters:  
  ARG_TYPE  
  Template   parameter   specifying   the   type   of   arguments   referencing   elements   in   this   array.  
  newElement  
  The   element   to   be   added   to   this   array.  
     
  TYPE&   CArray::operator   []   (int   nIndex);  
  Parameters:  
  TYPE  
  Template   parameter   specifying   the   type   of   elements   in   this   array.  
  nIndex  
  Index   of   the   element   to   be   accessed.  
  Remarks:  
  Returns   the   array   reference   of   element   at   the   specified   index.  
     
  1) 材料二:CList  
  template<class   TYPE,   class   ARG_TYPE>class   CList   :   public   CObject  
  Parameters:  
  TYPE  
  Type   of   object   stored   in   the   list.  
  ARG_TYPE  
  Type   used   to   reference   objects   stored   in   the   list.   Can   be   a   reference.  
  Remarks:  
  The   CList   class   supports   ordered   lists   of   nonunique   objects   accessible   sequentially   or   by   value.    
  CList   lists   behave   like   doubly-linked   lists.    
     
  void   CList::AddTail(ARG_TYPE   newElement);  
  Parameters:  
  ARG_TYPE  
  Template   parameter   specifying   the   type   of   the   list   element   (can   be   a   reference).  
  newElement  
  The   element   to   be   added   to   this   list.  
  Remarks:  
  Adds   a   new   element   or   list   of   elements   to   the   tail   of   this   list.   The   list   can   be   empty   before   the   operation.  
   
  2) 材料三:   realloc  
  realloc  
  Reallocate   memory   blocks.  
  void   *realloc(void   *memblock,   size_t   size);  
  Return   Value:  
  The   return   value   points   to   a   storage   space   that   is   guaranteed   to   be   suitably   aligned   for   storage   of   any   type   of   object.   To   get   a   pointer   to   a   type   other   than   void,   use   a   type   cast   on   the   return   value.  
  Remarks:  
  The   size   argument   gives   the   new   size   of   the   block,   in   bytes.   The   contents   of   the   block   are   unchanged   up   to   the   shorter   of   the   new   and   old   sizes,   although   the   new   block   can   be   in   a   different   location.   Because   the   new   block   can   be   in   a   new   memory   location,   the   pointer   returned   by   realloc   is   not   guaranteed   to   be   the   pointer   passed   through   the   memblock   argument.  
     
  3) 请指出下面这段代码可能会出现的问题  
  CList<VARIANT*,   VARIANT*>   g_ValueList;  
  CArray<VARIANT,   const   VARIANT&>   g_ValuePool;  
  void   AddNewValue   (const   VARIANT&   newValue)  
  {  
  g_ValueList.AddTail(&g_ValuePool[g_ValuePool.Add(newValue)]);  
  }  
   
   
   
  4. 阅读以下程序,纠正其中的错误。(40分钟)  
  //------------------------------------------------------------------  
  class   CCelsius  
  {  
  public:  
  CCelsius()   {   m_nC   =   0;   }  
    ~CCelsius()   {}  
   
  short   ToFahrenheit()   {   return   m_nC   *   9   /   5   +   32;   }  
  void     SetC(short   nCelsius) {   m_nC   =   nCelsius;   }  
  short   GetC()   {   return   m_nC;   }  
   
  protected:  
  short   m_nC;  
  };  
   
  class   CFahrenheit  
  {  
  public:  
  CFahrenheit()   {   m_nF   =   0;   }  
    ~CFahrenheit()   {}  
   
  short   ToCelsius()       {   return   (m_nF   -   32)   *   5   /   9;   }  
  void     SetF(short   nFahrenheit)   {   m_nF   =   nFahrenheit;   }  
  short   GetF()       {   return   m_nF;   }  
   
  protected:  
  short   m_nF;  
  };  
   
  class   CTemperature   :   public   CCelsius   ,   public   CFahrenheit  
  {  
  public:  
  CTemperature();  
  ~CTemperature();  
   
  BOOL   CreateLevel(UINT   nSize);  
  void   ReleaseLevel();  
  UINT   GetLevel(int   nCelsius);  
   
  protected:  
  UINT         m_nSize;  
  short*     m_pLevel;  
  };  
   
  //------------------------------------------------------------------  
   
  CTemperature::CTemperature()  
  {  
  m_nSize     =   0;  
  m_pLevel   =   NULL;  
  }  
   
  CTemperature::~CTemperature()  
  {    
  ReleaseLevel();  
  }  
   
  BOOL   CTemperature::CreateLevel(UINT   nSize)  
  {  
  ASSERT(m_pLevel   ==   NULL);  
  if   (m_pLevel)  
  return   FALSE;  
   
  m_pLevel   =   new   short[nSize];  
  if   (m_pLevel   ==   NULL)  
  return   FALSE;  
   
  for   (UINT   i   =   0;   i   <   nSize;   i++)  
  m_pLevel[i]   =   100   *   i   *   i;  
   
  m_nSize   =   nSize;  
  return   TRUE;  
  }  
   
  void   CTemperature::ReleaseLevel()  
  {  
  if   (m_pLevel)  
  {  
  delete   []   m_pLevel;  
  m_nSize     =   0;  
  m_pLevel   =   NULL;  
  }  
  }  
   
  UINT   CTemperature::GetLevel(int   nT)  
  {  
  ASSERT(m_pLevel);  
   
  for   (UINT   nLevel   =   0;   nLevel   <   m_nSize;   nLevel++)  
  {  
  if   (m_pLevel[nLevel]   >   nT)  
  break;  
  }  
  return   nLevel;  
  }  
   
  void   OutC(CCelsius*   pC)  
  {  
  if   (pC)  
  printf("摄氏%d度等于华氏%d度\n",   pC->GetC(),   pC->ToFahrenheit());  
  }  
   
  void   OutF(CFahrenheit*   pF)  
  {  
  if   (pF)  
  printf("华氏%d度等于摄氏%d度\n",   pF->GetF(),   pF->ToCelsius());  
  }  
   
  void   OutL(CTemperature*   pT)  
  {  
  if   (pT)  
  {  
  printf("摄氏%d度的等级为:%d\n",   pT->GetC(),   pT->GetLevel(pT->GetC()));  
  printf("华氏%d度的等级为:%d\n",   pT->GetF(),   pT->GetLevel(pT->GetF()));  
  }  
  }  
   
  void   main()  
  {  
  CTemperature*   pTemperature   =   new   CTemperature;  
  if   (pTemperature   ==   NULL)  
  return;  
  CCelsius*   pCelsius   =   (CCelsius*)pTemperature;  
  pCelsius->SetC(100);  
  OutC(pCelsius);  
  CFahrenheit*   pFahrenheit   =   (CFahrenheit*)pCelsius;  
  pFahrenheit->SetF(400);  
  OutF(pFahrenheit);  
  pTemperature->CreateLevel(3);  
  OutL(pTemperature);  
  CTemperature*   pTempOther   =   new   CTemperature;  
  if   (pTempOther   ==   NULL)  
  return;  
  *pTempOther   =   *pTemperature;  
  delete   pFahrenheit;  
  OutL(pTempOther);  
  delete   pTempOther;  
  }  
   
  5. C++程序设计  
  1) 写出以下程序的运行结果:  
  #include   <iostream>  
  class   Base  
  {  
  public:  
  Base()  
  {  
  cout   <<   "Base()"   <<   endl;  
  }  
  Base(const   Base   &theBase)  
  {  
  cout   <<   "Base(const   Base   &theBase)"   <<   endl;  
  }  
  ~Base()  
  {  
  cout   <<   "~Base()"   <<   endl;  
  }  
  void   Open()  
  {  
  OnOpen();  
  }  
  private:  
  virtual   void   OnOpen()   =   0;  
  };  
   
  class   Derived   :   public   Base  
  {  
  public:  
  Derived()  
  {  
  cout   <<   "Derived()"   <<   endl;  
  }  
  Derived(const   Derived   &theDerived)  
  {  
  cout   <<   "Derived(const   Derived   &theDerived)"   <<   endl;  
  }  
  ~Derived()  
  {  
  cout   <<   "~Derived()"   <<   endl;  
  }  
  private:  
  virtual   void   OnOpen()  
  {  
  //这里可能抛出异常  
  }  
  };  
  Base   *CreateInstance()  
  {  
  return   new   Derived();  
  }  
   
  int   main()  
  {  
  Base   *pBase   =   ::CreateInstance();  
  if   (pBase)  
  {  
  pBase->Open();  
  delete   pBase;  
  }  
  return   0;  
  }  
   
  2) 在1)中,类Base和类Derived的实现有没有问题?如果有,如何修改?  
   
   
   
   
  3) 说明1)中类Base的Open函数和OnOpen函数的设计目的和意义。  
   
   
   
   
  4) 使用STL技术修改main()函数中的代码,使之成为异常安全的。  
   
  问题点数:50、回复次数:23Top

1 楼vcpb(yeah)回复于 2005-12-22 20:43:23 得分 0

你敲进去的么,强Top

2 楼sankt(做最好的自己)回复于 2005-12-22 20:50:33 得分 0

5.我来回到第五题  
  #include   <iostream>  
  using   namespace   std;  
   
  class   Base  
  {  
  public:  
  Base()  
  {  
  cout   <<   "Base()"   <<   endl;  
  }  
   
  Base(const   Base   &theBase)  
  {  
  cout   <<   "Base(const   Base   &theBase)"   <<   endl;  
  }  
  virtual   ~Base()  
  {  
  cout   <<   "~Base()"   <<   endl;  
  }  
  void   Open()  
  {  
  OnOpen();  
  }  
  private:  
  virtual   void   OnOpen()   =   0;  
  };  
   
  class   Derived   :   public   Base  
  {  
  public:  
  Derived()  
  {  
  cout   <<   "Derived()"   <<   endl;  
  }  
  Derived(const   Derived   &theDerived)  
  {  
  cout   <<   "Derived(const   Derived   &theDerived)"   <<   endl;  
  }  
  virtual   ~Derived()  
  {  
  cout   <<   "~Derived()"   <<   endl;  
  }  
  private:  
  virtual   void   OnOpen()  
  {  
  //这里可能抛出异常  
   
  }  
  };  
   
  Base   *CreateInstance()  
  {  
  return   new   Derived();  
  }  
   
  int   main()  
  {  
  Base   *pBase   =   ::CreateInstance();  
   
          if   (pBase)  
  {  
  pBase->Open();  
  delete   pBase;  
  }  
  system("pause");  
   
  return   0;  
  }Top

3 楼sankt(做最好的自己)回复于 2005-12-22 20:55:58 得分 0

1)中输出  
  Base()  
  Derived()  
  ~Base()  
  2)在1)中,类Base和类Derived的实现有没有问题?如果有,如何修改?  
  修改如上面的程序  
  析构函数必须是virtual的.  
   
  多态的实现于访问控制的修饰符没有关系。  
  3)说明1)中类Base的Open函数和OnOpen函数的设计目的和意义。  
  更好的实现了面向接口编程  
   
   
  4)   使用STL技术修改main()函数中的代码,使之成为异常安全的。  
  //======  
   
  Top

4 楼sankt(做最好的自己)回复于 2005-12-22 20:58:29 得分 0

题目不错,我要好好想想  
  Top

5 楼manplus(魅力加加)回复于 2005-12-22 23:15:32 得分 0

markTop

6 楼Mr_Yang(初级程序员)回复于 2005-12-22 23:23:23 得分 0

markTop

7 楼iamcaicainiao(老菜 ◆无为莫千钧●恨水梦少白▼)回复于 2005-12-23 07:54:27 得分 0

我靠,这哪个公司的,像我英文这么菜的。呵呵。抽空再慢慢研究Top

8 楼fine10000(好心情)回复于 2005-12-23 08:27:07 得分 0

学习.Top

9 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2005-12-23 08:53:22 得分 0

CList<VARIANT*,   VARIANT*>   g_ValueList;  
  CArray<VARIANT,   const   VARIANT&>   g_ValuePool;  
  void   AddNewValue   (const   VARIANT&   newValue)  
  {  
  g_ValueList.AddTail(&g_ValuePool[g_ValuePool.Add(newValue)]);  
  }  
   
  =================================================================  
  这个应该是楼主写反了,   这个程序是没有问题的,因为CList里面存的是指针,    
  g_ValuePool[g_ValuePool.Add(newValue)]返回的是引用,   是g_ValuePool里面  
  的内容的引用,  
  &g_ValuePool[g_ValuePool.Add(newValue)是g_ValuePool内容的地址  
   
  如果  
            CArray<VARIANT,   const   VARIANT&>   g_ValuePool;  
  改成  
          CArray<VARIANT,   const   VARIANT>   g_ValuePool;  
  g_ValuePool[g_ValuePool.Add(newValue)]返回的是临时变量,    
  &g_ValuePool[g_ValuePool.Add(newValue)]就是临时变量的地址,  
  这就错了,  
   
  我想应该是这个样子吧,    
   
   
   
  Top

10 楼chengzanmiao(高薪為共產當多納稅)回复于 2005-12-23 09:16:47 得分 0

markTop

11 楼MarcoCC(成长与不断的跌倒和失败)回复于 2005-12-23 09:35:44 得分 0

大致看了下第四题:  
  void   main()  
  {  
  CTemperature*   pTemperature   =   new   CTemperature;  
  if   (pTemperature   ==   NULL)  
  return;  
  CCelsius*   pCelsius   =   (CCelsius*)pTemperature;  
  pCelsius->SetC(100);  
  OutC(pCelsius);  
  CFahrenheit*   pFahrenheit   =   (CFahrenheit*)pCelsius;   //这个类型转换是不安全的  
  pFahrenheit->SetF(400);  
  OutF(pFahrenheit);  
  pTemperature->CreateLevel(3);  
  OutL(pTemperature);  
  CTemperature*   pTempOther   =   new   CTemperature;  
  if   (pTempOther   ==   NULL)  
  return;  
  *pTempOther   =   *pTemperature;     //这将导致两个指针指向同一块new出来的内存区  
  delete   pFahrenheit;  
  OutL(pTempOther);  
  delete   pTempOther;     //重复delete同一块new出来的内存区,异常  
                                          //此外pTemperature原指向的那块new的内存泄漏  
  }Top

12 楼lj197912(从零开始)回复于 2005-12-23 09:51:21 得分 0

CList<VARIANT*,   VARIANT*>   g_ValueList;  
  CArray<VARIANT,   const   VARIANT&>   g_ValuePool;  
  void   AddNewValue   (const   VARIANT&   newValue)  
  {  
  g_ValueList.AddTail(&g_ValuePool[g_ValuePool.Add(newValue)]);  
  }  
  =========================  
  我觉得问题是因为CList元素的类型是VARIANT*所以有可能造成,g_ValuePool元素修改会令g_ValueList的元素也跟着改变.而且有可能内存泄漏。g_ValueList析构掉会引起g_ValuePool内容的释放Top

13 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2005-12-23 10:11:22 得分 0

g_ValueList析构掉会引起g_ValuePool内容的释放  
  ====================================  
  开玩笑,Top

14 楼iamcaicainiao(老菜 ◆无为莫千钧●恨水梦少白▼)回复于 2005-12-23 10:12:32 得分 0

to     sankt(黄景天)  
  你的输出结果肯定有问题吧。drived既然构造了,就不惜购了?Top

15 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2005-12-23 10:22:41 得分 0

CList<VARIANT*,   VARIANT*>   g_ValueList;  
  CArray<VARIANT,   const   VARIANT&>   g_ValuePool;  
  void   AddNewValue   (const   VARIANT&   newValue)  
  {  
  g_ValueList.AddTail(&g_ValuePool[g_ValuePool.Add(newValue)]);  
  }  
  ===========================================================  
  我想错了,   这个代码的问题是:  
  如果当CArray添加元素的时候,   可能会重新申请内存,   这个时候CList里面的指针会失效  
  如果CArray使用ralloc的申请策略,在ralloc成功的情况下不会有问题Top

16 楼HuangQQ(黄QQ)回复于 2005-12-23 10:25:24 得分 0

先寒一个。。。。。。  
  啥公司的面试题,这么恐怖??Top

17 楼ericqxg007(还有很多东西要学(卡卡一米阳光))回复于 2005-12-23 11:12:18 得分 0

markTop

18 楼fflush(stdin)回复于 2005-12-23 11:16:23 得分 0

我想错了,   这个代码的问题是:  
  如果当CArray添加元素的时候,   可能会重新申请内存,   这个时候CList里面的指针会失效  
  如果CArray使用ralloc的申请策略,在ralloc成功的情况下不会有问题  
   
  ---------------------------------------------  
  realloc成功的情况下,整个内存块也有可能被转移到新的地方,所以也是有问题的Top

19 楼MarcoCC(成长与不断的跌倒和失败)回复于 2005-12-23 11:59:21 得分 0

to     sankt(黄景天)  
  你的输出结果肯定有问题吧。drived既然构造了,就不惜购了?  
   
  sankt(黄景天)的结果是正确的,由于没有声明成虚析构,当Base析构时不会去调用derived的析构函数。  
  Top

20 楼luvybird()回复于 2005-12-23 13:18:47 得分 0

markTop

21 楼corrupt(喜欢 睡在床板下 的思考)回复于 2005-12-23 14:29:54 得分 0

这个公司   还是   不错的Top

22 楼lj197912(从零开始)回复于 2005-12-23 16:17:51 得分 0

CList<VARIANT*,   VARIANT*>   g_ValueList;  
  CArray<VARIANT,   const   VARIANT&>   g_ValuePool;  
  void   AddNewValue   (const   VARIANT&   newValue)  
  {  
  g_ValueList.AddTail(&g_ValuePool[g_ValuePool.Add(newValue)]);  
  }  
  =====================  
  g_ValueList   的VARIANT*内存如何管理?如果delete   的话,会出现什么情况?Top

23 楼GGeneral2(阿弥陀佛)回复于 2005-12-26 00:49:41 得分 0

大难!大难!Top

你可能对以下的问题也比较感兴趣....