如果在派生类内重载了基类的非虚拟函数:
#includeusing namespace std; class B{ public: void p(int m) { cout<<"B::p "< p(a1); pd1->p(a2); cout< p(a1); pd2->p(a2); return 0; } 运行程序输出: D::p 1 //通过对象调用,在派生类中基类的p(int m)版本被p(long m)掩盖,调用的是派生类版本 D::p 2 B::p 1 //通过指针调用,根据指针的静态类型B *pd1,调用的是基类版本 B::p 2 D::p 1 //通过指针调用,根据指针的静态类型D *pd2,调用的是派生类版本 D::p 2
关于可见性问题,可以通过using在派生类中声明基类版本来解决:
#includeusing namespace std; class B{ public: void p(int m) { cout<<"B::p "< p(a1); pd1->p(a2); cout< p(a1); pd2->p(a2); return 0; } 运行程序输出: B::p 1 //通过对象调用,由于在派生类中开放了基类版本的可见性,因此实现了正确的重载调用 D::p 2 B::p 1 //通过基类指针调用,根据指针的静态型别,在基类中匹配函数,因此调用的是基类版本 B::p 2 B::p 1 //通过基类指针调用,根据指针的静态型别,在派生类中匹配函数,因此实现了正确的重载调用 D::p 2
结论:
1.如果不通过using在派生类中声明基类版本的可见性,那么派生类内重载的非虚拟函数会掩盖基类版本。也就是说,基类中只有基类的版本,派生类中只有派生类的版本。
2.如果通过using在派生类中声明基类版本的可见性,那么派生类内可以看到基类版本,即:基类只有基类的版本,派生类中同时有基类和派生类的版本。
3.不论是通过对象调用还是指针调用,都是按照对象和指针声明时的静态类型,到对应的类中匹配可调用的版本。也就是说基类对象和基类指针(无所谓是否指向派生类对象)在基类范围内匹配函数;派生类对象和派生类指针在派生类范围内匹配函数。



