我正在与一位同事讨论为什么在Visual Studio 2008中无法编译以下内容:

class base
{
protected:
    virtual void f(){}
};

class a : public base
{
public:
    void fa(base* pb)
    {
        pb->f(); // error C2248: 'base::f' : cannot access protected member declared in class 'base'
    }
};

他认为这是完全合理的,但是我认为这是一个奇怪的限制,如果我希望base及其所有派生类成为一个封闭系统,我仍然需要将base的某些成员公开,以便他们都可以与每个人交谈其他都是通过共享接口(interface),它们都是公开地派生的。

我是否有一些用例,我没有想到允许在哪些地方访问这些 protected 成员会破坏 protected 成员的性质?

最佳答案

如果编译器允许此类操作,则可以轻松破坏封装。考虑一下:

base b;
a foo;
foo.fa(b); // we can now easily access/modify protected elements of `b`

在这种情况下,派生对象foo和基本b之间没有关系,但是您可以使用派生对象来访问其“内脏”。这应该是不可能的(至少是恕我直言)。

只需在f()中执行a.fa()即可,因为您只修改了a的基础部分,而不是一些无关的对象。

更具体地说,您可以编写一个“包装器”,该包装器将为任何类禁用protected:
#include <iostream>

class Base
{
public: // protected in your case, public here so it compiles
    int x{42};
public:
    int getx() {return x;}
};

template<typename T> // wrapper
class DisableProtected: public T
{
public:
    void modify(Base* b)
    {
        b->x = 24;
    }
};

int main()
{
    Base base;
    std::cout << base.getx() << std::endl;
    DisableProtected<Base> foo;

    foo.modify(&base); // can modify any Base
    std::cout << base.getx() << std::endl;
}

关于c++ - 关于 protected 成员函数和派生类访问的困惑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29437724/

10-10 18:29
查看更多