`

C++私有继承和保护继承

    博客分类:
  • C++
阅读更多
private继承的话,原来父类的public ,protected成员继承到子类中,并成为private类型成员;
protected继承的话,原来父类的public ,protected成员继承到子类中,并成为protected类型成员;
public继承的话,原来父类的public ,protected成员继承到子类中,类型不变

本文目录
如何表达“私有继承”
“私有继承”和“组合(Composition)”如何相似
我应该优先使用“组合(Composition)”还是“私有继承”
我是否应该把一个私有继承类的指针转化为基类指针
“保护继承”与“私有继承”具有哪些相关性
“私有继承”和“保护继承”有什么使用规则


如何表达“私有继承”
继承时使用 private 关键字,而不是 public。例如:

class Foo : private Bar {
public:
   ...
};

“私有继承”和“组合(Composition)”如何相似
私有继承是组合(Composition)的一个语法表达上的变种。例:

Car Has-A Engine 这种关系用简单的组合可以表达为:

class Engine {
public:
   Engine(int numCylinders);
   void start();                 // Starts this Engine
};

class Car {
public:
   Car() : e_(8) { }             // Initializes this Car with 8 cylinders
   void start() { e_.start(); }  // Start this Car by starting its Engine
private:
   Engine e_;                    // Car has-a Engine
};

它还可以使用私有继承来表达:

class Car : private Engine {    // Car has-a Engine
public:
   Car() : Engine(8) { }         // Initializes this Car with 8 cylinders
   using Engine::start;          // Start this Car by starting its Engine
};

以上两个方案有一些相似之处:

在两个方案里,每个 Car 对象都仅拥有一个 Engine 对象。
客户都无法将 Car* 转换为 Engine*。
两个方案里的 Car 类都有一个 start() 方法用来调用包含的 Engine 对象的 start() 方法。
也有一些不同之处:

当你打算让每个 Car 拥有多个 Engine 时,你需要使用组合(Composition)。
私有继承会引入不必要的多重继承。
私有继承允许成员将 Car* 转换为 Engine*。
私有继承允许访问基类的 protected 成员。
私有继承允许 Car 重载 Engine 的虚函数。
私有继承使得 Car 拥有 start() 方法稍稍简单一些(简单地调用 Engine 的 start() 即可)。
需要注意的是,私有继承通常会用来获得对基类的 protected 成员的访问权,但这并不是一个长远的解决方案。

我应该优先使用“组合(包含)”还是“私有继承”
尽量使用组合,必要时才使用私有继承。

一般情况下,你并不需要访问太多其它类的内部,私有继承就给了你这样的一种能力以及责任。但私有继承并不 evil,只是它的维护过于昂贵,因为它把某人更改了某个东西导致破坏掉你的代码的可能性提高了。

私有继承的一个正统的、长远的使用方法是:当你打算建立一个class Fred 使用 class Wilma 的代码,并且 class Wilma 的代码需要调用你的新类 class Fred 的成员函数。在这种情况下,Fred 调用 Wilma 的 non-virtual 函数,Wilma 调用自身的 pure virtual 函数(它们在 Fred 中被重载)。使用组合很难实现这个目的。

class Wilma {
protected:
   void fredCallsWilma()
     {
       std::cout <<"Wilma::fredCallsWilma()\n";
       wilmaCallsFred();
     }
   virtual void wilmaCallsFred() = 0;   // A pure virtual function
};

class Fred : private Wilma {
public:
   void barney()
     {
       std::cout <<"Fred::barney()\n";
       Wilma::fredCallsWilma();
     }
protected:
   virtual void wilmaCallsFred()
     {
       std::cout <<"Fred::wilmaCallsFred()\n";
     }
};

我是否应该把一个私有继承类的指针转换为基类指针
一般来说,不应该。

从私有继承类的成员函数和友员函数来看,派生类与基类的关系是已知的。将 PrivatelyDer* 向上转化为 Base*(或者是 PrivatelyDer& 到 Base&)是安全的,不需要也不建议使用转换。

尽管如此,用户应该避免这种行为。当这种转换是私有继承类的 private 行为时,转换没有任何通知。

“保护继承”与“私有继承”具有哪些相关性
相似点:都允许重载虚函数。都不代表与基类是 Is-A 的关系。

不同点:保护继承允许子类的子类知道继承关系,孙子类实际上暴露有实现细节。这样既有好处,也有代价。好处是孙子类可以利用它与基类的关系。代价是如果子类不潜在地打破进一步派生的类,它就无法改变这种关系。(我翻译地实在太汗了,贴上原文吧:This has both benefits (it allows derived classes of the protected derived class to exploit the relationship to the protected base class) and costs (the protected derived class can't change the relationship without potentially breaking further derived classes). )

“私有继承”和“保护继承”有什么使用规则
拿下面的这几个类为例:

class B                    { /*...*/ };
class D_priv : private   B { /*...*/ };
class D_prot : protected B { /*...*/ };
class D_publ : public    B { /*...*/ };
class UserClass            { B b; /*...*/ };

没有一个派生类可以访问 B 的 private 部分。
在 D_priv 中,B 的 public 和 protected 部分是 private 的。
在 D_prot 中,B 的 public 和 protected 部分是 protected 的。
在 D_publ 中,B 的 public 部分是 public,protected 部分是 protected,因为 D_publ Is-A B。
UserClass 仅可访问 B 的 public 部分,因为 B 对内部实现进行了封装。
要让 B 的 public 方法在 D_priv 或 D_prot 中也是 public,需要使用 B:: 前缀,例:让 B::f(int, float) 方法在 D_prot 也是 public,应该写为:

class D_prot : protected B {
public:
   using B::f;  // Note: Not using B::f(int,float)
};

分享到:
评论

相关推荐

    C++公有继承、保护继承和私有继承的区别

    C++提供了三种不同的继承方式,每种方式对基类成员的访问权限有不同的规定,分别是公有继承(public inheritance)、保护继承(protected inheritance)和私有继承(private inheritance)。 1. 公有继承(public ...

    C++中公有继承、私有继承、保护继承.的含义及例子

    C++中public继承、private继承、protected继承的例子

    C/C++ 公有继承、保护继承和私有继承的对比详解

    C++ 提供了三种继承方式:公有继承(public inheritance)、保护继承(protected inheritance)和私有继承(private inheritance),每种方式都有不同的访问权限和行为。 1. **公有继承(Public Inheritance)** -...

    C++面向对象程序设计习题继承与派生.pdf

    在C++中,继承方式有三种:公有继承、私有继承和保护继承。 公有继承是指基类中的公有成员和保护成员在派生类中仍然是公有成员和保护成员。基类中的私有成员在派生类中不可访问。公有继承的优点是可以继承基类的...

    c++继承与派生

    本节课程主要介绍C++中继承与派生的概念和使用方法,包括公有继承、私有继承和保护继承等不同的继承方式。通过实验和实践,掌握继承与派生的基本概念和使用方法。 继承的概念 继承是面向对象编程中的一种机制,它...

    c++程序设计 继承与派生实验(二)

    继承方式主要有三种:公有继承(public inheritance)、私有继承(private inheritance)和保护继承(protected inheritance)。在公有继承下,基类的公有和保护成员在派生类中保持相同访问级别;私有继承则使基类的...

    C++类继承内存布局详解图(一目了然)

    在继承方面,C++提供了多种继承方式,包括单继承、多重继承和虚继承。每种继承方式都对应着不同的内存布局。例如,在单继承中,子类的成员变量和基类的成员变量会被合并到一起。在多重继承中,每个基类的成员变量...

    C++重点复习题(多态和继承).doc

    继承方式有三种:公有、私有和保护。多继承中,多个基类具有同名成员,在它们的子类中访问这些成员,就产生了二义性,但进行访问时,不能存在二义性。赋值兼容规则是指派生类对象可以当作基类对象使用,只要存在继承...

    c++继承的视频

    - **私有继承(private)**:基类的公有和保护成员在子类中变为私有。 - **保护继承(protected)**:基类的公有成员在子类中变为保护,保护成员保持不变。 4. **虚函数与多态** - **虚函数(virtual function)...

    详解C++编程中的私有继承和公有继承

    C++类的私有继承 在声明一个派生类时将基类的继承方式指定为private的,称为私有继承,用私有继承方式建立的派生类称为私有派生类(private derived class ), 其基类称为私有基类(private base class )。 私有基类的...

    C++ 中私有继承的作用

    C++ 中私有继承的作用 私有继承的 第一个规则:和公有继承相反,如果两个类之间的继承关系为私有,编译器一般不会将派生类对象转换成基类对象。 第二个规则: 从私有基类继承而来的成员都成为了派生类的私有成员,...

    C++继承与派生课件

    - **私有继承(private)**:基类的所有成员在派生类中都被视为私有,包括原本的公有和保护成员。派生类内部可以访问基类的公有和保护成员,但外部代码不能直接访问基类的任何成员。 - **保护继承(protected)**...

    c++继承与派生的相关资料

    私有继承通常用来表示“is-implemented-in-terms-of”关系,即派生类是用基类实现的,但并不表示“is-a”关系。 5.4.3 保护成员和保护继承(Protected Inheritance) 保护继承方式下,基类的公有和保护成员在派生类...

    C++继承与派生机制详解

    C++支持三种不同的继承方式:私有继承、保护继承和公有继承。每种继承方式都会影响到派生类成员以及通过派生类对象访问基类成员的权限。 1. **私有继承(Private Inheritance)** - 私有继承将基类中的公有和保护...

    C++实现继承

    - **私有继承**:父类的公有成员和保护成员在子类中变为私有成员。 #### 继承的语法 在C++中,定义继承的语法非常直接,形式如下: ```cpp class 派生类名 : 继承方式 基类名 { 新增成员声明; }; ``` 其中,...

    C++随堂测试(继承、多态、重载)(答案).docx

    继承可以分为公有继承、私有继承和保护继承三种,分别对应基类成员的访问权限。公有继承中,基类的公有成员和保护成员在派生类中保持不变;私有继承中,基类的所有成员在派生类中变为私有成员;保护继承中,基类的...

    c++继承分类

    6. 继承中的访问控制:解释公有继承、保护继承和私有继承的区别,以及它们对子类访问权限的影响。 7. 小结和最佳实践:总结继承的使用场景,提供关于何时以及如何使用继承的最佳实践。 通过学习这个视频教程,你将...

    C++继承与派生

    私有继承下,基类的公有和保护成员在派生类中将变为私有;而保护继承则使得基类的公有成员在派生类中变为保护成员。 #### 5.2 派生类的构造函数和析构函数 派生类的构造函数需要调用基类的构造函数来初始化继承自...

Global site tag (gtag.js) - Google Analytics