Confusion regarding protected member functions and derived class access
我正在与一位同事讨论为什么在Visual Studio 2008中无法编译以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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' } }; |
他认为这是完全合理的,但是我认为这是一个奇怪的限制,如果我想让
我是否有一些用例,我不考虑允许访问这些受保护成员的地方会破坏受保护成员的性质吗?
近重复项:
- 具有受保护字段的细微C ++继承错误
- 我可以从派生类中的静态函数访问受保护的基类成员吗?
- 父类中受保护的数据在子类中不可用?
- 访问父级受保护的变量
Is there some use case I'm not thinking of where allowing access to these protected members could break the nature of protected members?
我相信这是为了防止一个派生类与同级派生类的不变量混淆。考虑
1 2 3 4 5 6 7 8 9 10 11 | class A { protected: void foo(); }; class B : public A { // complicated code }; class C : public A { void bar(B* b) { b->foo(); } }; |
这有效地允许
如果编译器允许这样的事情,那么您可以轻松地破坏封装。考虑一下:
1 2 3 | base b; a foo; foo.fa(b); // we can now easily access/modify protected elements of `b` |
在这种情况下,派生对象
只需在
更具体地说,您可以编写一个"包装器",该包装器将对任何类禁用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #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; } |
好笑的故事。我刚收到比尼亚(Bjarne)关于这个问题的回复。这是他的回应。
考虑
1 2 3 4 5 6 7 8 9 | class B : public base { public: // ... }; A a; B b; a.f(&b); // a manipulated b's base |
这引起了细微的错误。这有效:
1 2 3 4 5 6 7 8 | class A : public base { public: void fa(base* pb) { f(); // use your own base } }; |