C++调用普通基类的私有/保护函数

3
在以下示例中,有没有一种好的方式可以从B :: bar()调用A :: foo()?
class A {
protected:
  void foo() {}
};

class B : public A {
public:
  void bar(A& a) { // edit: called with &a != this
    a.foo(); // does not work
  }
};

我想到的唯一方法就是将B声明为A的友元,但如果有更多的类的话,这种方法可能会变得非常混乱。
你有什么其他的想法吗?

为什么B::bar需要调用A::foo?如果A::foo是受保护的,那就意味着只有类型为A和任何派生自A的类型的对象才能调用它。如果你真的需要从一个无关的类中调用A::foo,也许它不应该被保护。 - James McNellis
BA类型时,将A实例传递给B的原因是什么? - wkl
@Mihran 第一句话是问题。 - BЈовић
我并不打算在 *this 上使用 B::bar,而是在其他实例上使用(实际上是在 A 的其他子类上使用)。A::foo() 有其保护的原因,我正在编写一个库,不希望开发人员使用它。 - lucas clemente
没有简单的方法,因为您想要打破正常的访问保护规则。不过,绕过受保护的访问是可能的。http://stackoverflow.com/questions/3364722/accessing-protected-member-of-template-parameter/3365221#3365221 - CB Bailey
为什么你要这么做呢?如果你必须这样做,那就去做,并且你应该将其视为一个好朋友(不要试图通过继承来绕过保护机制,试着使用可用的功能)。也许对你想做的事情进行精确描述会有所帮助,这些假设只能做到这个程度。 - Martin York
3个回答

4

是的,您可以使用基类函数。

class A {
protected:
  void foo() {}
  void do_other_foo(A& ref) {
      ref.foo();
  }
};

class B : public A {
public:
  void bar(A& a) { // edit: called with &a != this
    this->do_other_foo(a);
  }
};

当然,那个能工作。虽然不是很好看,但可能是最好的解决方案。谢谢! - lucas clemente

3

为什么要传递A类型的对象?你可以这样做:

class B : public A {
public:
  void bar() {
    foo();
  }
};

或者像这样

class B : public A {
public:
  void bar() {
    A::foo();
  }
};

我并不打算在 *this 上使用 B::bar,而是在其他实例上使用(实际上是在 A 的其他子类上使用)。 - lucas clemente
@lucas 听起来像是一个设计问题。为什么foo()被保护了? - BЈовић
请看我上面的帖子,我不希望我的库之外的类/函数使用它。 - lucas clemente

1
这是一种提供“受保护”访问权限的方法,允许任何派生类或对象进行调用。它使用了一种受保护的令牌类型,需要解锁特权方法:
struct A
{
protected:
    //Zero sized struct which allows only derived classes to call privileged methods
    struct DerivedOnlyAccessToken{};

public:     //public in the normal sense :
    void foo() {}

public:     //For derived types only :
    void privilegedStuff( DerivedOnlyAccessToken aKey );
};

struct B: A
{
    void doPrivelegedStuff( A& a )
    {
        //Can create a token here
        a.privilegedStuff( DerivedOnlyAccessToken() );
    }
};

int _tmain(int argc, _TCHAR* argv[])
{

    A a;
    a.foo();
    a.privilegedStuff( A::DerivedOnlyAccessToken() ); // compile error.

    B b;
    b.doPrivelegedStuff( a );

    return 0;
}

这不是我的想法。我在某个地方读到过。抱歉,我不记得是谁的狡猾主意。

我希望编译器可以省略aKey参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接