注:下面是我自己最近看书的总结,应该有错误
在C++中,如果子类与父类的函数名相同,那么子类将覆盖父类中同名的函数,也就是说,在继承关系中,方法签名只由方法名决定。若想实现多态效果,那么只能使用虚函数来实现。父类中的虚函数可能被编译为一个指针,编译子类时将子类相应的函数地址赋值给那个指针。
我想,继承在向上和向下两个方向起作用:
向上:子类可以使用父类中public和protected的方法和变量,实现代码重用。
向下:父类中的虚函数由不同的子类实现,实现多态。
在这个模型中,容易出问题的地方应该在“覆盖”上。子类对象赋值给父类变量后,执行的是父类中的函数,而不是自身的函数。这样一是容易使人陷入困惑,二是增大了对象的体积。所以我认为在设计时要尽量避免这种情况。如果是特意追求这种效果,一定要在注释中对此进行说明。
例如下面的代码:
#include <iostream> using namespace std; class Base { public: virtual void f(float x){cout << "Base::f(float)" << x <<endl;} void g(float x){cout << "Base::g(float)" << x <<endl;} void h(float x){cout << "Base::h(float)" << x <<endl;} }; class Derived:public Base { public: void f(float x){cout << "Derived::f(float)" << x << endl;} void g(int x){cout << "Derived::g(int)" << x << endl;} void h(float x, float y){cout << "Derived::h(float, float)" << x << y <<endl;} }; int main(void){ Derived d; d.f(3.14); d.g(3.14); d.h(3.14); return 0; } 在编译时就会报错:BaseDerived.cpp: In function ‘int main()’:
BaseDerived.cpp:26:10: error: no matching function for call to ‘Derived::h(double)’
BaseDerived.cpp:26:10: note: candidate is:
BaseDerived.cpp:16:8: note: void Derived::h(float, float)
BaseDerived.cpp:16:8: note: candidate expects 2 arguments, 1 provided
说明父类中的g(int)和h(float)被“覆盖”了。
这与Java中是不一样的,Java中只是函数名相同不会覆盖,而是实现了“重载”,例如:
class Base{ public void f(double x){System.out.println("Base.f(double):" + x);} public void g(double x){System.out.println("Base.f(double):" + x);} } class Derived extends Base{ public void f(int x){System.out.println("Derived.f(int): " + x);} public void g(double x, double y) {System.out.println("Derived.f(double, double): " + x + " " + y);} } class BaseDerived{ public static void main(String args[]){ Derived d = new Derived(); d.f(3.14); d.g(3.14); } } 运行结果:Base.f(double):3.14
Base.f(double):3.14
说明尽管子类中定义了同名的f(int)和g(double, double),但父类中的f(double)和g(double)仍能使用。