从基类指针访问派生私有成员函数到派生对象

发布于 2024-11-06 13:25:37 字数 772 浏览 5 评论 0原文

可能的重复:
为什么我可以通过指向派生对象的基类指针访问派生私有成员函数?

#include <iostream>
using namespace std;

class B {
public:
  virtual void fn1(void) {cout << "class B : fn  one \n"; }
  virtual void fn2(void) {cout << "class B : fn  two \n"; }
};

class D: public B {
    void fn1(void) {cout << "class D : fn one \n"; }
private:
    void fn2(void) {cout << "class D : fn two \n"; }
};

int main(void)
{
    B *p = new D;

    p->fn1();
    p->fn2();
}

为什么即使fn2,p->fn2()也会调用派生类函数D 中是私有的?

Possible Duplicate:
Why can i access a derived private member function via a base class pointer to a derived object?

#include <iostream>
using namespace std;

class B {
public:
  virtual void fn1(void) {cout << "class B : fn  one \n"; }
  virtual void fn2(void) {cout << "class B : fn  two \n"; }
};

class D: public B {
    void fn1(void) {cout << "class D : fn one \n"; }
private:
    void fn2(void) {cout << "class D : fn two \n"; }
};

int main(void)
{
    B *p = new D;

    p->fn1();
    p->fn2();
}

Why does p->fn2() call the derived class function even though fn2 is private in D ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

白衬杉格子梦 2024-11-13 13:25:37

访问修饰符,例如 publicprivateprotected 仅在编译期间强制执行。当您通过指向基类的指针调用该函数时,编译器不知道该指针指向派生类的实例。根据编译器可以从这个表达式推断出的规则,这个调用是有效的。

降低派生类中成员的可见性通常是语义错误。现代编程语言(例如 Java 和 C#)拒绝编译此类代码,因为在基类中可见的成员始终可以通过基指针在派生类中访问。

Access modifiers, such as public, private and protected are only enforced during compilation. When you call the function through a pointer to the base class, the compiler doesn't know that the pointer points to an instance of the derived class. According to the rules the compiler can infer from this expression, this call is valid.

It is usually a semantic error to reduce the visibility of a member in a derived class. Modern programming languages such as Java and C# refuse to compile such code, because a member that is visible in the base class is always accessible in the derived class through a base pointer.

笨笨の傻瓜 2024-11-13 13:25:37

调用p->fn2() 在运行时根据p 指向的对象类型进行评估。在编译时,编译器将 p->fn2() 调用视为对 B::fn2() 的调用,并且自 B::fn2()< /code> 是公共的,编译器不仅仅报告错误。仅在运行时才会评估实际的函数调用 D::fn2()

这并没有违反封装原则,这是 C++ 的一项功能,称为运行时多态性动态多态性

The call p->fn2() is evaluated at run time depending on the type of objected pointed by p. At compile time the compile sees the p->fn2() call as call to B::fn2() and since B::fn2() is public the compiler doesn't report only error. It is only at runtime that actual function call D::fn2() is evaluated.

This doesn't break the Encapsulation principle this is a feature of C++ called Run-time Polymorphism or Dynamic Polymorphism

今天小雨转甜 2024-11-13 13:25:37

当您执行 p = new D 时,p->__vfptr 现在指向 D 的虚拟函数表的开头。由于这种情况发生在运行时,因此访问说明符不会发挥作用。

When you do p = new D , p->__vfptr is now pointing to the start of the virtual function table of D. And since this happens at runtime, therefore, access specifiers don't come into play.

岁月染过的梦 2024-11-13 13:25:37

来自维基百科

在 OOP 中,当派生类继承
基类,派生的对象
类可以被称为(或转换)为
要么是基类类型要么
派生类类型。如果有
被重写的基类方法
派生类,方法调用
行为不明确。

虚拟和虚拟之间的区别
非虚拟解决了这种歧义。
如果有问题的函数是
在基类中指定为“虚拟”
然后是派生类的函数
将被调用(如果存在)。如果它
不是虚拟的,基类的
函数将被调用。

HTH。

From wikipedia:

In OOP when a derived class inherits a
base class, an object of the derived
class may be referred to (or cast) as
either being the base class type or
the derived class type. If there are
base class methods overridden by the
derived class, the method call
behaviour is ambiguous.

The distinction between virtual and
non-virtual resolves this ambiguity.
If the function in question is
designated "virtual" in the base class
then the derived class's function
would be called (if it exists). If it
is not virtual, the base class's
function would be called.

HTH.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文