猿问

关于c++的一个有趣现象,具体看下面详细情况?

c++有趣现象:private的成员函数可以在类的外部调用?

#include <iostream.h>
class base;
base * pbase;
class base
{
public:
base()
{pbase=this;}
virtual void fn()
{cout<<"base"<<endl;}
};
class derived:public base
{private:<br/> void fn()<br/> {cout<<"derived"<<endl;}
};
void main()
{
derived aa;
pbase->fn();
}

以上程序在VC和VC7中输出结果为 derived, 哈,居然private的成员函数可以在类的外部调用.

//我的问题是,难道这是真的吗?private的成员函数可以在类的外部调用.?
//还是这个private关键字不应该使用?

BIG阳
浏览 230回答 2
2回答

慕容3067478

它并不是C++的缺陷或是被设计者所忽视的问题。当我们使用虚函数的时候,它的访问规则是在声明的时候被确定的,而不是在被“子类重写”(overridden)的时候,虚函数的访问规则不会受到来自被重写的子类函数的影响,更进一步说,当某个对象A的引用B(特指间接访问)用来调用该对象的虚函数时,对于该对象A的一切声明信息,都取决于该对象的引用B,而不是这个引用所引用的对象A。C++标准里有对该问题的具体说明:当一个子类函数通过基类的指针调用时,访问权限取决于基类对该函数的声明。参考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 invokedpd->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.至少我们在程序编译时无法获知这个指针的值,它会指向何种位置。经验:private仅仅是一个访问限定符,它只限定函数和数据不能被“直接”访问,而不担保这些函数和数据会被通过其他方法间接地访问到,在成员函数中返回一个类私有数据成员的引用也是这个道理。

泛舟湖上清波郎朗

发现新大陆了呵呵,不错,但是,它并不是C++的缺陷或是被设计者所忽视的问题。当我们使用虚函数的时候,它的访问规则是在声明的时候被确定的,而不是在被“子类重写”(overridden)的时候,虚函数的访问规则不会受到来自被重写的子类函数的影响,更进一步说,当某个对象A的引用B(特指间接访问)用来调用该对象的虚函数时,对于该对象A的一切声明信息,都取决于该对象的引用B,而不是这个引用所引用的对象A。C++标准里有对该问题的具体说明:当一个子类函数通过基类的指针调用时,访问权限取决于基类对该函数的声明。参考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 invokedpd->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.至少我们在程序编译时无法获知这个指针的值,它会指向何种位置。经验:private仅仅是一个访问限定符,它只限定函数和数据不能被“直接”访问,而不担保这些函数和数据会被通过其他方法间接地访问到,在成员函数中返回一个类私有数据成员的引用也是这个道理。另外,如果不是特殊的需要,一般来说,这并不是一个好的设计,有点自找麻烦的味道!
随时随地看视频慕课网APP
我要回答