简体   繁体   English

有效的C ++:阻止受保护的继承?

[英]Effective C++: discouraging protected inheritance?

I was reading Scott Meyers' Effective C++ (third edition), and in a paragraph in Item 32: Make sure public inheritance is "is-a" on page 151 he makes the comment (which I've put in bold): 我正在阅读Scott Meyers的Effective C ++ (第三版),在第32项的一段中:确保公共继承是第151页的“is-a” ,他发表了评论(我以粗体显示):

This is true only for public inheritance. 这仅适用于公共继承。 C++ will behave as I've described only if Student is publicly derived from Person. 只有当Student公开派生于Person时,C ++才会表现得如我所描述的那样。 Private inheritance means something entirely different (see Item 39), and protected inheritance is something whose meaning eludes me to this day. 私有继承意味着完全不同的东西(见第39项), 受保护的继承是我今天的意义所在。

The question : how should I interpret this comment? 问题是 :我该如何解释这个评论? Is Meyers trying to convey that protected inheritance is seldom considered useful and should be avoided? 迈耶斯试图传达受保护的遗产很少被认为是有用的,应该避免吗?

(I've read the question Difference between private, public, and protected inheritance as well as C++ FAQ Lite's private and protected inheritance section , both of which explain what protected inheritance means, but hasn't given me much insight into when or why it would be useful.) (我已经阅读了私有,公共和受保护的继承以及C ++ FAQ Lite的私有和受保护的继承部分 之间区别 问题 ,这两个部分都解释了受保护的继承意味着什么,但是没有让我深入了解何时或为什么它会有用。)

Some scenarios where you'd want protected: 您需要保护的一些场景:

  1. You have a base class with methods where you know you never want to expose the functionality outside, but you know will be useful for any derived class. 您有一个基类,其中包含您不知道在外部公开函数的方法,但您知道这对任何派生类都有用。

  2. You have a base class with members that should be logically used by any class that extends that class, but should never be exposed outside. 你有一个基类,其成员应该被任何扩展该类的类逻辑地使用,但不应该暴露在外面。

Thanks to multiple inheritance you can play around with base classes' inheritance type and construct a more diversed class with existing logic and implementation. 由于多重继承,您可以使用基类的继承类型,并使用现有的逻辑和实现构建更多样化的类。

A more concrete example: 一个更具体的例子:

You could create a few abstract classes that follow Design Pattern logic, lets say you have: 你可以创建一些遵循设计模式逻辑的抽象类,假设你有:

Observer
Subject
Factory

Now you want these all to be public, because in general, you could use the pattern on anything. 现在你希望这些都是公开的,因为一般来说,你可以在任何东西上使用这个模式。

But, with protected inheritance, you can create a class that is an Observer and Subject, but only protected factory, so the factory part is only used in inherited classes. 但是,使用受保护的继承,您可以创建一个Observer和Subject类,但只创建受保护的工厂,因此工厂部分仅用于继承的类。 (Just chose random patterns for the example) (只是为示例选择了随机模式)

Another example: 另一个例子:

Lets say for example you want to inherit from a library class (not that I encourage it). 让我们说例如你想从一个库类继承(不是我鼓励它)。 Lets say you want to make you own cool extension of std::list<> or a "better" shared_ptr . 让我们说你想让你拥有std::list<>或“更好”的shared_ptr的酷扩展。

You could derive protectedly from the base class (which is designed to have public methods). 您可以从基类(设计为具有公共方法)中受到保护。
This will give you the option to use your own custom methods, use the class' logic, and pass the logic to the to any derived class. 这将使您可以选择使用自己的自定义方法,使用类的逻辑,并将逻辑传递给任何派生类。

You could probably use encapsulation instead, but inheritance follows the proper logic of IS A (or in this case IS sort of A) 你可能会使用封装,但是继承遵循IS A的正确逻辑(或者在这种情况下是IS的A类)

He isn't exactly discouraging protected inheritance, he just says that he hasn't found any good use for it. 他并没有完全劝阻受保护的遗产,他只是说他没有找到任何好的用途。 I haven't seen anyone either elsewhere. 我还没有见过其他人。

If you happen to find a couple of really useful use cases, you might have material to write a book too. 如果您碰巧找到了几个非常有用的用例,那么您可能也有写一本书的材料。 :-) :-)

Yes and no. 是的,不是。 I myself think that protected inheritance is a bad feature too. 我自己认为受保护的继承也是一个不好的特性。 It basicly imports all the base class's public and protected members as protected members. 它基本上将所有基类的公共成员和受保护成员导入为受保护成员。

I usually avoid protected members, but on the lowest levels requiring extreme efficiency with a compiler with bad link-time optimization they are useful. 我通常会避免使用受保护的成员,但是对于需要极高效率的最低级别,编译器具有错误的链接时优化,它们很有用。 But everything built on that shouldn't be messing with the original base class's (data) members and use the interface instead. 但是基于它的所有内容都不应该与原始基类(数据)成员混淆,而是使用接口。

What I think Scott Meyer is trying to say, is that you can still use protected inheritance if it solves a problem, but make sure to use comments to describe the inheritance because it's not semantically clear. 我认为Scott Meyer试图说的是,如果它解决了问题,你仍然可以使用受保护的继承,但是请确保使用注释来描述继承,因为它在语义上并不清晰。

Yup, there aren't many uses for protected or private inheritance. 是的,受保护或私有继承的用途并不多。 If you ever think about private inheritance, chances are composition is better suited for you. 如果你想过私人继承,那么组合更有可能适合你。 (Inheritance means 'is-a' and composition means 'has-a'.) (继承意味着'is-a',而组合意味着'has-a'。)

My guess is that the C++ committee simply added this in because it was very easy to do and they figured, "heck, maybe someone will find a good use for this". 我的猜测是,C ++委员会只是添加了这个,因为它很容易做到,他们认为,“哎呀,也许有人会发现这个很好用”。 It's not a bad feature, it doesn't do any harm, just that no one has found any real use for it yet. 这不是一个糟糕的功能,它没有任何伤害,只是没有人发现任何真正的用途。 :P :P

I don't know if Meyers is advising us to refrain from using protected inheritance, but it seems you should avoid it if Meyers is on your team, because at least he won't be able to understand your code. 我不知道Meyers是否建议我们不要使用受保护的继承,但如果Meyers在你的团队中,你似乎应该避免它,因为至少他无法理解你的代码。

Unless your co-workers know C++ better than he does, you should probably also stay away from protected inheritance. 除非你的同事比他更了解C ++,否则你应该远离受保护的继承。 Everybody will understand the alternative, ie using composition. 每个人都会理解替代方案,即使用构图。

I can imagine however a case where it could make sense: You need access to a protected member in a class whose code you can't change but you don't want to expose an IS-A relationship. 我可以想象一下它可能有意义的情况:您需要访问类中受保护的成员,其代码无法更改,但您不希望公开IS-A关系。

class A {
protected:
  void f(); // <- I want to use this from B!
};

class B : protected A {
private:
  void g() { f(); }
};

Even in that case, I would still consider making a wrapper with public inheritance that exposes the protected base members with public methods, then compose with these wrappers. 即使在这种情况下,我仍然会考虑使用公共继承来创建一个包装器,该包装器使用公共方法公开受保护的基本成员,然后使用这些包装器进行组合。

/*! Careful: exposes A::f, which wasn't meant to be public by its authors */
class AWithF: public A {
public:
  void f() { A::f(); }
};

class B {
private:
  AWithF m_a;
  void g() { m_a.f(); }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM