今天写代码竟然发现,private成员函数竟然可以在类的外部调用,开始以为是C++设计的缺陷。但是逐步深入才知道C++多态的博大精深。
- #include <iostream>
- using namespace std;
- class Base
- {
- public:
- virtual void Func()
- {
- cout<<"base"<<endl;
- }
- };
- class Derived : public Base
- {
- private:
- void Func()
- {
- cout<<"derived"<< endl;
- }
- };
- int main()
- {
- Base *d = new Derived;
- d->Func( );
- delete d;
- return 0;
- }
#include <iostream> using namespace std; class Base { public: virtual void Func() { cout<<"base"<<endl; } }; class Derived : public Base { private: void Func() { cout<<"derived"<< endl; } }; int main() { Base *d = new Derived; d->Func( ); delete d; return 0; }
查看了一下资料,发下了下面的内容,这下一下子就明了了。
- /*参考C++ Standard ISO/IEC 14882:2003(E) 第11.6节:
- 11.6 Access to virtual functions [class.access.virt]
- The access rules (clause 11) for a virtual function are determined by
- its declaration and are not affected by the rules for a function that
- later overrides it.
- [Example:
- */
- class B {
- public:
- virtual int f();
- };
- class D : public B {
- private:
- int f();
- };
- void f()
- {
- D d;
- B* pb = &d;
- D* pd = &d;
- pb->f(); //OK: B::f() is public,
- // D::f() is invoked
- pd->f(); //error: D::f() is private
- }
- /*—end example]
- Access is checked at the call point using the type of the
- expression used to denote the object for which the member
- function is called (B* in the example above).
- The access of the member function in the class in which
- it was defined (D in the example above) is in general not known.
- */
/*参考C++ Standard ISO/IEC 14882:2003(E) 第11.6节: 11.6 Access to virtual functions [class.access.virt] The access rules (clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [Example: */ class B { public: virtual int f(); }; class D : public B { private: int f(); }; void f() { D d; B* pb = &d; D* pd = &d; pb->f(); //OK: B::f() is public, // D::f() is invoked pd->f(); //error: D::f() is private } /*—end example] Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known. */我们知道C++多态的包括编译时多态和运行时多态,而通过基类的指针或者引用调用虚函数时,会发生动态的绑定,而编译器的处理是静态的,它只会在调用该成员函数的时候,在当前类的作用域中进行访问控制检查(Base类或者B类中f函数是public的,因此可以通过编译器的检查),而对C++运行过程中的动态绑定(由于使用了基类的指针调用虚函数,程序运行时动态执行了子类的函数f())是不为所知,也就出现了上面的那段代码,外部直接调用了Derived的私有函数成员,而编译器却不为所知。
我们可以想像:当一个子类的虚成员函数通过基类的指针调用时,访问权限取决于基类对该函数的声明,而C++中private和proected仅仅是一个访问限定符,它只限定函数和数据不能被“直接”访问,而不担保这些函数和数据会被通过其他方法间接地访问到,在成员函数中返回一个类私有数据成员的引用,在外部就可以对这个私有属性进行修改(这个请参照博主的另一篇博客,对这个现象有说明)也是这个道理。
转载:http://blog.csdn.net/gatieme/article/details/17589981