如何访问受保护的基类函数,从派生类通过基类ptr



我有抽象类A,从中继承了许多类。在派生类中,我试图通过指针访问受保护的函数。但是我得到一个编译错误。

class A
{
   protected:
        virtual  void f()=0;
};
class D : public A
{
    public:
         D(A* aa) :mAPtr(aa){}
         void g();
    protected:
         virtual void f();
    private:
      A* mAPtr; // ptr shows to some derived class instance
};
void D::f(){  }

void D::g()
{
   mAPtr->f();
}

编译器错误提示:不能访问在类A中声明的受保护成员A::f。

如果我声明mAPtr为D*,而不是A*,一切都编译。我不明白为什么会这样

依赖于private访问对相同类型的不相关实例有效。

依赖protected访问可以在相同类型(以及更多派生类型)的不相关实例上工作。

但是,依赖于protected访问,不能在不相关的基类型实例上工作。

[n3290: 11.5/1]: 派生类的友元或成员函数类引用受保护的非静态成员函数或protected在基类的非静态数据成员中应用访问检查除了前面第11条所述的之外。除了成型时指向成员(5.3.1)的指针,必须通过指针进行访问对派生类本身(或任何类)的对象的引用或引用派生自该类)(5.2.5)。如果访问是为了形成一个指针对于成员,嵌套名称说明符应命名派生类(或(从该类派生的任何类)

所以D或者从D衍生出来的东西,而不是A

这是c++中一个经常被质疑的可爱的奇怪之处,尽管如此,它还是被设计成试图避免陷阱。毕竟,您不知道*mAPtr 真正的类型是什么。

包含protected section的类意味着该类允许派生类以他们选择的任何方式操作它们的基类(只要受保护的接口允许)。

类D对象可以操作它们自己的A部分。在这样做的过程中,他们可能想要保持一些不变量。

假设存在(或将来会有!)另一个类E,也继承自A。类E对象也可以操作它们自己的A部分,并且它们可能强制不同的不变量。

现在,如果一个类D对象被允许操作任何对象的a部分,它就不能保证不变量。一个D对象可能会对E对象的A部分做一些事情,从而破坏了E对象。这就是为什么它是不允许的。


但是如果你真的想,也许有一种方法可以调用a::f,而不暴露给所有人,那就是通过朋友函数。

class A;
namespace detail
{
   void call_f(A*);
}
class A
{
   friend void detail::call_f(A*);
private:
   virtual void f() = 0;
};
namespace detail
{
   void call_f(A* a) { a->f(); }
}
class D: public A
{
public: 
    void g() { detail::call_f(mAPtr); }
private: 
    void f() {}
    A* mAPtr;
};

这依赖于用户足够自律,远离名称空间,其名称清楚地表明它包含实现细节。

您忘记在类声明后使用;:

class A
{
   protected:
       virtual  void f()=0;
};
class D : public A
{
    public:
        void g();
    protected:
        void f();
    private:
       A* mAPtr; // ptr shows to some derived class instance
};

此外,不需要存储基类指针

最新更新