链接时突然无法访问私有方法

时间:2014-02-04 10:21:27

标签: c++

我有一个简单的类层次结构,包含基类和派生类。基类有两个派生类调用的受保护成员。来自最近的一些C#体验,我认为最好让界面更流畅并允许链接方法调用,因此不是调用this->A(),而是this->B(),你可以调用{{1} }}。但是,以下代码将无法编译:

this->A()->B()

这会产生以下编译器错误:

#include <iostream>

class Base
{
  protected:
    Base* A()
    {
      std::cout << "A called." << std::endl;    
      return this;
    }

    Base* B()
    {
      std::cout << "B called." << std::endl;    
      return this;
    }
};

class Derived : public Base
{
  public:
    void Test()
    {
        // Base::A and Base::B are private here.
        this->A()   // This works fine
            ->B();  // Suddenly I cannot access my own private method?
    }
};

int main()
{
    Derived d;
    d.Test();

    return 0;
}

我也尝试将基类方法设为虚拟,但这没有用。

我的C ++足够生疏,我似乎无法弄清楚这里发生了什么,所以非常感谢帮助。我也想知道这是不是一个坏主意,因为main.cpp: In member function 'void Derived::Test()': main.cpp:12:15: error: 'Base* Base::B()' is protected Base* B() ^ main.cpp:26:21: error: within this context ->B(); // Suddenly I cannot access my own private method? ^ 和C ++ - 人们不习惯这样流畅的界面。

5 个答案:

答案 0 :(得分:8)

类中的受保护成员只能通过派生类从派生类访问,即通过派生类的对象,或引用或指向该派生类。

A()的返回类型是Base*,它不是派生类,这就是您无法访问其受保护成员的原因。编译器不会跟踪它是否真正引用同一个对象。

答案 1 :(得分:2)

是的,您无法从Base调用Base *类的受保护方法。您可以认为受保护的方法是私有的,区别在于它们也变得属于派生类。

答案 2 :(得分:2)

这是正确的行为,你不能为你只能通过派生类调用的另一个类调用受保护的函数,因为当你调用this->A()时它会返回一个不同类的Base *。原因是,如果你做了类似的事情,

class Derived : public Base
{
  public:
    void Test()
    {
       baseInstance->B(); // this shouldn't be possible. If the case was you can call it through a pointer or an object this would be possible.
    }

    Base* baseInstance; 
};

同样最好指出派生的和this可能没有相同的地址,它可能有不同的地址。当您实际将Base*强制转换为Derived*时,编译器将处理地址的差异,如果像static_cast<Derived*>(this->A())->B();

那样完成,这就有可能

答案 3 :(得分:2)

要添加到Sebastian,可以通过以下方式解决这个问题,但不是很好:

static_cast<Derived*>(this->A())->B();

答案 4 :(得分:2)

您可以参考标准来获得问题的答案

11.2基类和基类成员的可访问性[class.access.base]

  

如果

,则可在R处访问N的基类B.
— an invented public member of B would be a public member of N, or
— R occurs in a member or friend of class N, and an invented public member of B would be     
    a private or
    protected member of N, or
— R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
— there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R

如果您通过Base指针引用该成员,则上述子句均不满足。