如何从派生类访问基类中的受保护方法?

发布于 2024-10-11 20:10:49 字数 577 浏览 3 评论 0原文

这是令我烦恼的代码示例:

class Base {
  protected:
    virtual void foo() = 0;
};

class Derived : public Base {
  private:
    Base *b; /* Initialized by constructor, not shown here
                Intended to store a pointer on an instance of any derived class of Base */

  protected:
    virtual void foo() { /* Some implementation */ };
    virtual void foo2() {
      this->b->foo(); /* Compilator sets an error: 'virtual void Base::foo() is protected' */
    }
};

How do you access to protected overrided function?

感谢您的帮助。 :o)

Here is a sample of code that annoys me:

class Base {
  protected:
    virtual void foo() = 0;
};

class Derived : public Base {
  private:
    Base *b; /* Initialized by constructor, not shown here
                Intended to store a pointer on an instance of any derived class of Base */

  protected:
    virtual void foo() { /* Some implementation */ };
    virtual void foo2() {
      this->b->foo(); /* Compilator sets an error: 'virtual void Base::foo() is protected' */
    }
};

How do you access to the protected overrided function?

Thanks for your help. :o)

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

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

发布评论

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

评论(6

情徒 2024-10-18 20:10:50

一种解决方案是在 Base 中声明一个静态受保护函数,将调用重定向到私有/受保护函数(示例中的 foo)。

可以这么说:

class Base {
protected:
    static void call_foo(Base* base) { base->foo(); }
private:
    virtual void foo() = 0;
};

class Derived : public Base {
private:
    Base* b;
protected:
    virtual void foo(){/* Some implementation */};
    virtual void foo2()
    {
        // b->foo(); // doesn't work
        call_foo(b); // works
    }
};

这样,我们就不会破坏封装,因为 Base 的设计者可以做出显式选择,允许所有派生类相互调用 foo,同时避免将 foo 放入公共接口或显式地将 Base 的所有可能子类转换为友元。

此外,无论 foo 是否是虚拟的,或者是私有的还是受保护的,此方法都有效。

这里是上面代码的运行版本的链接,这里是同一想法的另一个版本,但有更多的业务逻辑。

One solution would be to declare a static protected function in Base that redirects the call to the private / protected function (foo in the example).

Lets say:

class Base {
protected:
    static void call_foo(Base* base) { base->foo(); }
private:
    virtual void foo() = 0;
};

class Derived : public Base {
private:
    Base* b;
protected:
    virtual void foo(){/* Some implementation */};
    virtual void foo2()
    {
        // b->foo(); // doesn't work
        call_foo(b); // works
    }
};

This way, we don't break encapsulation because the designer of Base can make an explicit choice to allow all derived classes to call foo on each other, while avoiding to put foo into the public interface or explicitly turning all possible subclasses of Base into friends.

Also, this method works regardless of whether foo is virtual or not, or whether it is private or protected.

Here is a link to a running version of the code above and here another version of the same idea with a little more business logic.

两人的回忆 2024-10-18 20:10:50

它有点脆弱,但是使用您在这里定义的类,这行不通吗?

virtual void foo2() {
  reinterpret_cast<Derived *>(this->b)->foo(); 
}

reinterpret_cast 指向基础对象的 VTABLE,并通过此成员访问器调用它。

It's a bit fragile, but with the classes you defined here, won't this work?

virtual void foo2() {
  reinterpret_cast<Derived *>(this->b)->foo(); 
}

The reinterpret_cast points at the VTABLE for the base object, and calls it through this members accessor.

枕花眠 2024-10-18 20:10:50

您可以使用作用域运算符 (Base::foo()) 显式调用基函数。但在本例中,基类没有定义 foo (它是纯虚拟的),因此当您说 this->b->foo(); 因为 b 时,实际上没有要执行的函数是指向 Base 而不是 Derived 的指针。

You call base functions explicitly with the scope operator (Base::foo()). But in this case, the Base class doesn't define foo (it's pure virtual), so there's actually no function to execute when you say this->b->foo(); since b is a pointer to Base and not Derived.

拥抱影子 2024-10-18 20:10:50

如何访问受保护的
重写函数?

- - 从哪里?

您只能通过继承来访问受保护的成员(同一类的方法除外)。举例来说,您有一个继承自 Derived1class Derived1,那么 Derived1 的对象可以调用 foo()

编辑:关于受保护访问说明符的 MSDN 文章

How do you access to the protected
overrided function?

--- from where?

You can access a protected member only via inheritance (apart from the methods of the same class). Say for example you have a class Derived1 which inherits from Derived, then objects of Derived1 can call foo().

EDIT: MSDN article on protected access specifier.

东京女 2024-10-18 20:10:49

基类中的受保护成员只能由当前对象访问。
因此,您可以调用 this->foo(),但不允许调用 this->b->foo()。这与 Derived 是否提供 foo 的实现无关。

此限制背后的原因是否则很容易绕过受保护的访问。您只需创建一个像 Derived 这样的类,突然间您就可以访问其他类(例如 OtherDerived)的部分内容,而这些部分本来是外人无法访问的。

Protected members in a base-class are only accessible by the current object.
Thus, you are allowed to call this->foo(), but you are not allowed to call this->b->foo(). This is independent of whether Derived provides an implementation for foo or not.

The reason behind this restriction is that it would otherwise be very easy to circumvent protected access. You just create a class like Derived, and suddenly you also have access to parts of other classes (like OtherDerived) that were supposed to be inaccessible to outsiders.

晨曦慕雪 2024-10-18 20:10:49

通常,您可以使用 Base::foo() 来完成此操作,它引用当前实例的基类。

但是,如果您的代码需要按照您尝试的方式执行此操作并且不允许这样做,那么您需要将 foo() 公开或将 Derived 设为 Base 的友元。

Normally, you would do it using Base::foo(), which refers to the base class of the current instance.

However, if your code needs to do it the way you're trying to and it's not allowed, then you'll need to either make foo() public or make Derived a friend of Base.

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