【c++】虚函数描述符override与C++中sizeof(string)

  在C++11中为了帮助程序员写继承结构复杂的类型,引入了虚函数描述符override,如果派生类在虚函数声明时使用了override描述符,那么该函数必须重载其基类中的同名函数,否则代码将无法通过编译。我们来看一下如代码清单2-25所示的这个简单的例子。
  
  代码清单2-25
  
  struct Base {
  
  virtual void Turing() = 0;
  
  virtual void Dijkstra() = 0;
  
  virtual void VNeumann(int g) = 0;
  
  virtual void DKnuth() const;
  
  void Print();
  
  };
  
  struct DerivedMid: public Base {
  
  // void VNeumann(double g);
  
  // 接口被隔离了,曾想多一个版本的VNeumann函数
  
  };
  
  struct DerivedTop : public DerivedMid {
  
  void Turing() override;
  
  void Dikjstra() override; // 无法通过编译,拼写错误,并非重载
  
  void VNeumann(double g) override; // 无法通过编译,参数不一致,并非重载
  
  void DKnuth() override; // 无法通过编译,常量性不一致,并非重载
  
  void Print() override; // 无法通过编译,非虚函数重载
  
  };
  
  // 编译选项:g++ -c -std=c++11 2-10-3.cpp
  
  在代码清单2-25中,我们在基类Base中定义了一些virtual的函数(接口)以及一个非virtual的函数Print。其派生类DerivedMid中,基类的Base的接口都没有重载,不过通过注释可以发现,DerivedMid的作者曾经想要重载出一个“void VNeumann(double g)”的版本。这行注释显然迷惑了编写DerivedTop的程序员,所以DerivedTop的作者在重载所有Base类的接口的时候,犯下了3种不同的错误:
  
  函数名拼写错,Dijkstra误写作了Dikjstra。
  
  函数原型不匹配,VNeumann函数的参数类型误做了double类型,而DKnuth的常量性在派生类中被取消了。
  
  重写了非虚函数Print。
  
  如果没有override修饰符,在代码清单2-25中,DerivedTop作者的4处可以编译过去 但是与他的愿意(想重载虚函数)有严重的偏差了 但是编译器不报错,继续编译下去 这样就难排查了。加上关键字override 这样编译器可以辅助检查是不是正确重载 。 如果没有override修饰符 DerivedTop的作者可能在编译后都没有意识到自己犯了这么多错误。因为编译器对以上3种错误不会有任何的警示。这里override修饰符则可以保证编译器辅助地做一些检查。我们可以看到,在代码清单2-25中,DerivedTop作者的4处错误都无法通过编译。
  
  此外,值得指出的是,在C++中,如果一个派生类的编写者自认为新写了一个接口,而实际上却重载了一个底层的接口(一些简单的名字如get、set、print就容易出现这样的状况),出现这种情况编译器还是爱莫能助的。不过这样无意中的重载一般不会带来太大的问题,因为派生类的变量如果调用了该接口,除了可能存在的一些虚函数开销外,仍然会执行派生类的版本。因此编译器也就没有必要提供检查“非重载”的状况。而检查“一定重载”的override关键字,对程序员的实际应用则会更有意义。
  
  还有值得注意的是,如我们在第1章中提到的,final/override也可以定义为正常变量名,只有在其出现在函数后时才是能够控制继承/派生的关键字。通过这样的设计,很多含有final/override变量或者函数名的C++98代码就能够被C++编译器编译通过了。但出于安全考虑,建议读者在C++11代码中应该尽可能地避免这样的变量名称或将其定义在宏中,以防发生不必要的错误。
  
  建议:如果派生类里面是像重载虚函数 就加上关键字override 这样编译器可以辅助检查是不是正确重载,如果没加这个关键字 也没什么严重的error 只是少了编译器检查的安全性

  // test_max.cpp : 定义控制台应用程序的入口点。
  
  #include "stdafx.h"
  
  #include <iostream>
  
  #include <string>
  
  using namespace std;
  
  int main(void)
  
  {
  
  string strArr1[]={"Cjc ","is ","a "};
  
  string *pStrArr1=new string[2];
  
  pStrArr1[0]="good";
  
  pStrArr1[1]="boy.";
  
  cout<<"string type‘s length is "<<sizeof(string)<<endl;
  
  for(int i=0;i<sizeof(strArr1)/sizeof(string);i++)
  
  {
  
  cout<<strArr1[i];
  
  }
  
  for(int i=0;i<sizeof(pStrArr1)/sizeof(string);i++)
  
  {
  
  cout<<pStrArr1[i];
  
  }
  
  system("pause");
  
  return 0;
  
  }
  
  bubuko.com,布布扣
  
  有以上的结果可知:在VS2010 windows7 32位操作系统中string类的长度为32字节(与string的实现有关)
  
  注意:sizeof不能求出动态分配的内存块大小,所以sizeof(pStrArr1)的结果为4

猜你喜欢

转载自www.cnblogs.com/aquariusunny/p/12729876.html
今日推荐