private成员函数竟然可以在类的外部调用

今天写代码竟然发现,private成员函数竟然可以在类的外部调用,开始以为是C++设计的缺陷。但是逐步深入才知道C++多态的博大精深。

  1. #include <iostream>  
  2.   
  3. using namespace std;   
  4. class Base  
  5. {  
  6. public:  
  7.     virtual void Func()  
  8.     {  
  9.         cout<<"base"<<endl;  
  10.     }  
  11. };  
  12.   
  13. class Derived : public Base  
  14. {  
  15. private:  
  16.     void Func()   
  17.     {  
  18.         cout<<"derived"<< endl;  
  19.     }  
  20. };  
  21.   
  22.   
  23. int main()  
  24. {  
  25.     Base *d = new Derived;  
  26.     d->Func( );  
  27.     delete d;  
  28.       
  29.     return 0;  
  30. }  
#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;
}

查看了一下资料,发下了下面的内容,这下一下子就明了了。

  1. /*参考C++ Standard ISO/IEC 14882:2003(E) 第11.6节: 
  2.  
  3. 11.6 Access to virtual functions [class.access.virt] 
  4.  
  5. The access rules (clause 11) for a virtual function are determined by  
  6. its declaration and are not affected by the rules for a function that  
  7. later overrides it.  
  8. [Example: 
  9. */  
  10. class B {  
  11. public:  
  12. virtual int f();  
  13. };  
  14. class D : public B {  
  15. private:  
  16. int f();  
  17. };  
  18. void f()  
  19. {  
  20. D d;  
  21. B* pb = &d;  
  22. D* pd = &d;  
  23. pb->f(); //OK: B::f() is public,  
  24. // D::f() is invoked  
  25. pd->f(); //error: D::f() is private  
  26. }  
  27. /*—end example] 
  28.  
  29. Access is checked at the call point using the type of the  
  30. expression used to denote the object for which the member  
  31. function is called (B* in the example above).  
  32. The access of the member function in the class in which  
  33. it was defined (D in the example above) is in general not known. 
  34.  
  35. */  
/*参考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++privateproected仅仅是一个访问限定符,它只限定函数和数据不能被“直接”访问,而不担保这些函数和数据会被通过其他方法间接地访问到,在成员函数中返回一个类私有数据成员的引用,在外部就可以对这个私有属性进行修改(这个请参照博主的另一篇博客,对这个现象有说明)也是这个道理。


转载:http://blog.csdn.net/gatieme/article/details/17589981

上一篇:JS 字符串编码函数(解决URL特殊字符传递问题):escape()、encodeURI()、encodeURIComponent()区别详解


下一篇:.Net执行cmd获取系统信息