Do these two classes violate encapsulation?

2020-06-16 01:25发布

class X
{
protected:
    void protectedFunction() { cout << "I am protected" ; }
};

class Y : public X
{
public:
    using X::protectedFunction;
};

int main()
{
    Y y1;
    y1.protectedFunction();
}

This way I am able to expose one of the functions of the base class.

  1. Doesn't this violate the encapsulation principle?
  2. Is there a specific reason as to why this is in standard?
  3. Is there any uses of this, or is it going to be changed in the new standard?
  4. Are there any open issues related to this in the standard?

10条回答
神经病院院长
2楼-- · 2020-06-16 01:56

You did it by yourself.
You could write

class Y : public X
{
public:
    void doA()
    {
       protectedFunction();
    }
};

int main()
{
    Y y1;
    y1.doA(); 
}

I don't see any reason to worry about it.
Protected functions are pieces of reusable logic in the inheritance tree. You can hide them if there is some internal logic or restriction or like in your case you can expose it if you are sure that this won't harm anyone.

查看更多
何必那么认真
3楼-- · 2020-06-16 01:56

I think it was Stroustrup himself that said the encapsulation and data integrity features built into C++ are designed to keep honest people honest, not to stop criminals.

查看更多
冷血范
4楼-- · 2020-06-16 02:04

From the language point of view, that is not more of a violation of encapsulation than creating a delegate method in the derived object:

class Y : public X
{
public:
    void protectedFunction() {
       X::protectedFunction();
    }
};

Once a method is protected, it is offered to the deriving classes to do with it as they wish. The intention for the using declaration was not changing the inherited methods access but rather avoiding problems with method hidding (where a public method in X would be hidden in type Y if a different overload is defined).

Now, it is a fact that due to the language rules it can be used to change the access level for 'used' methods as in your example, but that does not really open any hole in the system. At the end, derived classes cannot do anything more than what they could do before.

If the actual question is whether the particular usage is a violation of encapsulation from a design point of view (where design here is application design, not language design), then most probably yes. In exactly the same way that making internal data or methods public. If it was designed to be protected by the initial designer of X, then chances are that Y implementor did not want it to be public... (or offering a delegating method for the same purpose)

查看更多
5楼-- · 2020-06-16 02:07

No, I don't really see the problem.

Instead of using, you could have done this:

class X
{
protected:
    void protectedFunction() { cout << "i am protected" ; }
};

class Y : public X
{
public:
    void protectedFunction() { X::protectedFunction(); }
};

Any class can take any member that is visible to it, and decide to expose it publicly. It may be bad class design to do so, but it is certainly not a flaw in the language. The entire point in private or protected members is that the class itself must decide who should get access to the member. And if the class decides "I'm going to give the whole world access", then that is how the class is designed.

If we follow your logic through, then getter and setters violate encapsulation too. And sometimes they do. But not because the language is broken. Simply because you're choosing to design broken classes.

By making a member protected, you give derived classes the freedom to do anyting they like with the member. They can see it, so they can modify it, or expose it publicly. You chose to make this possible when you made the member protected. If you didn't want that, you should've made it private.

查看更多
▲ chillily
6楼-- · 2020-06-16 02:09

Yes it does and that's why protected has received a fair share of criticism.

Bjarne Stroustrup, the creator of C++, regrets this in his excellent book The Design and Evolution of C++:

One of my concerns about protected is exactly that it makes it too easy to use a common base the way one might sloppily have used global data....In retrospect, I think that protected is a case where "good arguments" and fashion overcame my better judgement and my rules of thumb for accepting new features.

查看更多
Lonely孤独者°
7楼-- · 2020-06-16 02:09

No.

To use the public method you should have an instance of Y this won't work:

int main()
{
    X y1;
    y1.protectedFunction();
}

If Y in its new definition exposes a new interface it's up the Y. X is still protected.

查看更多
登录 后发表回答