Nar*_*rek 12 c++ inheritance private protected
正如我们从文献中了解到的公共继承一样,子类(子类)的对象也可以被视为基类(超类)的对象.为什么当继承受到保护或私有时,子类的对象不能被视为超类的对象?
Mar*_*ork 21
因为你看不到它:
class Base
{
public: virtual ~Base() {}
};
class PublicDerived: public Base
{ };
class PrivateDerived: private Base
{ };
int main()
{
PublicDerived publicD;
PrivateDerived privateD;
Base& base1 = publicD;
Base& base2 = privateD; // ERROR
}
Run Code Online (Sandbox Code Playgroud)
因此,您无法使用可以使用Base对象的PrivateDerived对象.
所以它永远不会像Base类对象那样.
一般来说,您会在文献中(以及此处的其他答案)中发现protected/ private继承意味着该类不能用作base.事实(其他一些答案提示)是只有继承的可见性受操作的影响.该derived班是一base类,即使外部代码无法看到它.
任何friend或类都可以利用这种关系:
struct base {
virtual void foo() { std::cout << "base" << std::endl; }
};
void take_base( base& b ) {}
class derived : base // private {
friend base& to_base( derived& );
virtual void foo() { std::cout << "derived" << std::endl; }
public:
base & as_base() { return *this; }
void call_function() { take_base(*this); } // ok: inside derived, it knows that it is
// in fact a base
};
base& to_base( derived& d ) {
return d;
}
int main() {
derived d;
//d.foo(); // error
//take_base(d); // error
take_base( d.as_base() ); // ok, the conversion is performed internally where
// access is granted: print "derived"
take_base( to_base(d) ); // ok, the conversion is performed in a friend function
// that has access: print "derived"
}
Run Code Online (Sandbox Code Playgroud)
现在,虽然从技术上来说就是这种情况,但在语义上,当你使用private继承时,你试图建模的不是一个is-a而是一个implemented-in-terms-of关系.这是重要的部分:在阅读代码时,如果你看到private继承,你就不应该考虑is-a而是实现.
在考虑机制如何工作时,"为什么"很简单:因为受保护和私有继承意味着以这种方式工作.
尽管如此,这可能还不足以回答问题的意图.您可能会问" 如果您不能将结果对象用作基类的实例,为什么要有私有和受保护的继承?"
那么,非公共继承意味着促进"在两个类之间的关系中实现"(而公共继承促进了"is-a"关系).换句话说,您打算重用部分或全部基类功能来为您自己的使用者提供服务.
这种情况几乎总是通过聚合而不是继承更好地实现(即,具有"基础"类的成员对象),并且我甚至会说非公共继承是更好的事情.
看看这个是为了更长时间的写作,扩展了上述内容.
更新:作为下面的评论者,有一些(公认的罕见)非公开继承提供了架构功能的机制,否则这是不可能的.阅读它们,因为探索语言的边缘可能非常有启发性.但尝试尽可能少地做到这一点.
简而言之,因为私有继承是实现的继承,而不是接口的继承.私有子类Derived对象不是a Base,而是根据实现 Base.公众和受保护的成员Base是可见的Derived,但他们变得私人,因此外部世界无法进入.因此,私有继承可以被看作是一种特殊形式的成分,这实际上是很少需要在实践中.(而且受保护的继承实际上从来没有 - 实际上甚至Bjarne Stroustrup也不知道继承的保护意味着什么.)
public继承服务于is-a关系的目的.那是:
class A {};
class B : public A {};
Class B is a version of class A.
Run Code Online (Sandbox Code Playgroud)
private继承服务于has-a关系的目的.您可以使用容器模型使用私有继承来编写几乎任何类:
class A {};
class B : private A {};
Run Code Online (Sandbox Code Playgroud)
可以重写(为了清楚起见,通常应该重写):
class A {};
class B
{
private:
A a;
};
Run Code Online (Sandbox Code Playgroud)
protected继承是类似的private,但实际上几乎不应该使用(Scott Meyers和Herb Sutter都在各自的书中说明了这一点).
| 归档时间: |
|
| 查看次数: |
17167 次 |
| 最近记录: |