c++派生类转换为基类与public、protected、private继承的关系

在《c++primer第四版中文》中p579,对“派生类到基类转换的可访问性”讲的比较模糊,于是用visual studio 2008花了四个小时把大部分能想到的情况都试验了一下,得出如下结果。
这里的后代类指的是由基类派生的派生类派生出来的类。也就是类层次中的第三层。

当为public派生时:
 派生类定义体中:
  构造函数中:
   构造函数体中不能定义派生类对象(虽然能通过编译,但运行中会出现错误),但可以定义基类对象、指针和引用。
   可以定义派生类和基类的指针及引用。既然不能定义派生类对象,就无法初始化引用(引用必须在定义时初始化),也就无法让派生类的引用对基类引用初始化或赋值了。并且,派生类的指针也不能初始化,只能赋空值,这样派生类的指针就可以对基类指针初始化或赋值。但这么做似乎没有什么意义。
  复制控制成员:
   复制函数:
    可以定义派生类和基类的对象、指针、引用。
    除了派生类复制函数的功能不能使用外(即不能用派生类对象对派生类对象进行初始化),其它和用户代码中一样。
   赋值函数:
    可以定义派生类和基类的对象、指针、引用。
    除了派生类赋值函数的功能不能使用外(即不能用派生类对象对派生类对象进行赋值),其它和用户代码中一样。
   析构函数:
    构造函数体中不能定义派生类对象(虽然能通过编译,但运行中会出现错误),但可以定义基类对象。
  其它函数体中:
   可以定义派生类和基类的对象、指针、引用。
   情况和在派生类用户代码中一样。
  其它位置:
   只能定义派生类指针,能定义基类对象、指针和引用。
 后代类定义体中:
  所有成员函数中:
   可以定义派生类和基类的对象、指针、引用。
   情况和在派生类用户代码中一样。
  其它位置:
   可以定义派生类和基类的对象、指针、引用。
  后代类的用户代码:
   后代类对象可以对基类对象进行初始化和赋值;
   后代类对象的地址可以对基类的指针进行初始化和赋值;
   后代类的对象和引用可以对基类的引用进行初始化和赋值;
 派生类用户代码中:
  派生类对象可以对基类对象进行初始化和赋值;
  派生类对象的地址可以对基类的指针进行初始化和赋值;
  派生类的对象和引用可以对基类的引用进行初始化和赋值;

当为protected派生时:
 派生类定义体中:
  由于派生列表中的访问标号只对用户代码和后代派生类有影响,对派生类访问基类成员没有影响,所以,此处情况应该同上。
 后代类定义体中:
  派生类可以转换为基类;
  后代类可以转换为基类(注意:在构造函数和复制控制成员中的限制和派生类中一样);
 派生类用户代码中:
  派生类无法转换为基类;
  后代类无法转换为基类;

当为private派生时:
 派生类定义体中:
  由于派生列表中的访问标号只对用户代码和后代派生类有影响,对派生类访问基类成员没有影响,所以,此处情况应该同上。
 后代类定义体中:
  派生类无法转换为基类;
  后代类无法转换为基类;
 用户代码中:
  派生类无法转换为基类;
  后代类无法转换为基类;

下面是用来做试验的类层次,只举出几个例子。实际在试验过程中,每次只试验一种情况,试验完毕马上擦掉,以免影响接下来的试验结果。
  class A
  {
  public:
   A(const int &ru = 0)
    : base(ru) {}
   A(const A &pp)
    : base(pp.base) { A w; A s(w); } //试验复制控制函数里的情况,就是在这里面加定义和转换代码,这个
   virtual ~A() {}    //示例在用户使用此函数时会出错。例在main()中执行 A a; A b(a)。
  private:
   int base;
  protected:
  };

  class B :private A
  {
  public:
   B(const int &ru = 0, const int &ru2 = 0)
    : A(ru), bulk(ru2) { B a; } //试验构造函数里的情况,在这里加代码。这个示例,当用户在main()中定义B a;时就会出错。
   ~B() { B b; } //试验析构函数里的情况,在这里加代码。这个示例,在发生此类型的析构时就会出错。
  private:
   int bulk;
  protected:
  };

  class C : public B
  {
  public:
   C(const int &ru = 0, const int &ru2 = 0, const int &ru3 = 0)
    : B(ru, ru2), bulk2(ru3) {}
   void uuuu() { A a; B b; C c; a = b; a = c; } //试验其它函数里面的情况,在这里面加定义的转换代码,此示例可行,不会出现错误。
   ~C() {}
  private:
   int bulk2;
  protected:
  };


总结:在可以访问到基类public成员的地方,可以进行派生类到基类的转换。
在用visual studio 2008试验上述规则时,发现在类定义体中,构造函数里面不能定义本身类的对象,否则在用户代码中使用时,运行会出现错误;析构函数里面也不能定义本身类对象,运行时会出现错误;在复制函数里可以定义本身类对象,在这个函数内部不能使用本身的复制功能,否则运行时同样会出错;在赋值函数里也可以定义本身类对象,在这个函数里面也不能使用本身类的赋值功能,否则还是会出错;
在其它成员函数里面可以定义本身类的对象,也能使用复制控制功能。
在类定义体内,不属于成员函数的范围,只能定义本身类的指针或引用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值