先来复习下C++虚函数的特性:①重载函数需要与父类中虚函数的签名相同;②子类中的重载函数是否有virtual标识不影响继承树。按照这些特性,有如下代码
1 #include <iostream> 2 using namespace std; 3 4 class MethObject { 5 6 public: 7 virtual double Arith()=0; 8 virtual void Print()=0; 9 }; 10 11 class Printable:public MethObject { 12 13 public: 14 double Arith()=0; 15 void Print(){ 16 cout << "Output is: " << Arith() << endl; 17 } 18 }; 19 20 class Add2:public Printable { 21 22 public: 23 Add2(double a, double b):x(a), y(b) {} 24 double Arith() {return x+y;} 25 26 private: 27 double x, y; 28 }; 29 30 class Mul3:public Printable { 31 32 public: 33 Mul3(double a, double b, double c):x(a), y(b), z(c) {} 34 double Arith() {return x*y*z;} 35 36 private: 37 double x, y, z; 38 };
现在我们为了保持统一的打印风格,从而禁止Printable的子类重载Print虚函数,这就要用到C++11中的final关键字,做过Java的都知道finally关键字,他们的特性类似。
稍微修改下代码,就可以看到编译错误:
1 #include <iostream> 2 using namespace std; 3 4 class MethObject { 5 6 public: 7 virtual double Arith()=0; 8 virtual void Print()=0; 9 }; 10 11 class Printable:public MethObject { 12 13 public: 14 double Arith()=0; 15 void Print() final{ 16 cout << "Output is: " << Arith() << endl; 17 } 18 }; 19 20 class Add2:public Printable { 21 22 public: 23 Add2(double a, double b):x(a), y(b) {} 24 double Arith() {return x+y;} 25 void Print() { 26 cout << "This is disallowed!" << endl; 27 } 28 29 private: 30 double x, y; 31 }; 32 33 class Mul3:public Printable { 34 35 public: 36 Mul3(double a, double b, double c):x(a), y(b), z(c) {} 37 double Arith() {return x*y*z;} 38 39 private: 40 double x, y, z; 41 };
编译结果如下:
从编译器提示的信息,就可以很清楚的看到错误内容。
C++虚函数的第二个特性,会导致一个“跨层”的问题,看如下代码:
1 class A { 2 virtual void Test() = 0; 3 }; 4 5 class B:public A { 6 }; 7 8 class C:public B { 9 void Test(){} 10 };
类C中的Test函数仍然是虚函数,但是类C的继承者却不一定知道Test函数是否可以重载,或者还有一种情况,类C的继承者原意是想重载Test函数,但是手抖了下,写成了test(),在编译器看来这是OK的,会产生Test()与test()两个函数,但是在实际运用中,就会出现一些不必要的错误。为了解决这个问题,就需要用到override关键字(类似Java的修饰符中的@override)
1 #include <iostream> 2 using namespace std; 3 4 class A { 5 virtual void Test() = 0; 6 void test(); 7 }; 8 9 class B:public A { 10 }; 11 12 class C:public B { 13 void Test() override {} 14 void test() override {} 15 };
编译结果如下:
提示信息很清晰,一眼就能看懂,就不做过多解释了。