posts - 28, comments - 179, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

C++类继承关系问题

Posted on 2007-05-31 13:18 chemz 阅读(14969) 评论(10)  编辑 收藏 引用 所属分类: C++
                                 C++类继承关系问题
    在C++中继承主要有三种关系:public、protected和private。这三种继承关系中public
继承是最为常用的一种继承关系,代表了接口继承含义,而他们分别具体代表了什么含义呢?
1. public
   从语义角度上来说,public继承是一种接口继承,根据面向对象中的关系而言就是,子类
   可以代替父类完成父类接口所声明的行为,也就是必须符合“Liskov替换原则(LSP)”,
   此时子类可以自动转换成为父类的接口,完成接口转换。
   从语法角度上来说,public继承会保留父类中成员(包括函数和变量等)的可见性不变,
   也就是说,如果父类中的某个函数是public的,那么在被子类继承后仍然是public的。
   
2. protected
   从语义角度上来说,protected继承是一种实现继承,根据面向对象中的关系而言就是,
   子类不能代替父类完成父类接口所声明的行为,也就是不符合“Liskov替换原则(LSP)”,
   此时子类不能自动转换成为父类的接口,就算通过类型转换(static_cast和dynamic_cast)
   也会得到一个空指针。
   从语法角度上来说,protected继承会将父类中的public可见性的成员修改成为protected
   可见性,相当于在子类中引入了protected成员,这样一来在子类中同样还是可以调用父
   类的protected和public成员,子类的子类就也可以调用被protected继承的父类的protected
   和public成员。
   例如:
       class CSample1 {
       protected:
           void printProtected() {}
       public:
           void printPublic() {}
       };
       class CSample2 : protected CSample1 {
      
       };
       class CSample3 : public CSample2 {
           void print3() {
               printProtected();
               printPublic();
           }
       };
3. private
   从语义角度上来说,private继承是一种实现继承,根据面向对象中的关系而言就是,
   子类不能代替父类完成父类接口所声明的行为,也就是不符合“Liskov替换原则(LSP)”,
   此时子类不能自动转换成为父类的接口,就算通过类型转换(static_cast和dynamic_cast)
   也会得到一个空指针。
   从语法角度上来说,private继承会将父类中的public和protected可见性的成员修改成为
   private可见性,这样一来虽然子类中同样还是可以调用父类的protected和public成员,
   但是在子类的子类就不可以再调用被private继承的父类的成员了。
       class CSample1 {
       protected:
           void printProtected() {}
       public:
           void printPublic() {}
       };
       class CSample2 : private CSample1 {
      
       };
       class CSample3 : public CSample2 {
           void print3() {
               printProtected(); // 编译错误,不可以调用该函数
               printPublic();    // 编译错误,不可以调用该函数
           }
       };
 
    在面向对象的理论中有两种概念:接口、实现,所以就出现了所谓的接口继承和实现继
承两种关系。而protected和private就是实现继承中所要用到的,其实protected和private
两者则约束继承时并没有形成两种不同的继承类别,而仅仅只是为了方便C++类方法的传递
调用而设计的,其实在java这样面向对象要求更为严格的语言当中,没有实现继承,他必须
通过委托方式来完成这一概念,如果熟悉java就会明白,如果一个对象要使用另外一个对象
的接口功能,而自身又不能够充当该对象所扮演的角色时,就会通过委托来完成,这样一来
就必须在对象中包含一个委托对象,通过对象调用语法来完成功能;在C++中就可以通过
protected和private继承来完成java中的委托关系(当然C++也可以形成对象委托关系),
那么这种情况下protected继承就容许委托可以传递(也就是被多级子类调用),而private
继承是不容许委托被传递的。

Feedback

# re: C++类继承关系问题  回复  更多评论   

2007-05-31 14:16 by walkspeed
透彻。
要是能继续讨论下protected和private继承类的子类被约束了的访问所代表的意义就更妙啦。

# re: C++类继承关系问题  回复  更多评论   

2007-05-31 14:57 by chemz
楼上的提的非常好。
在面向对象的理论中有两种概念:接口、实现,所以就出现了所谓的接口继承和实现继承两种关系。而protected和private就是实现继承中所要用到的,其实protected和private两者则约束继承时并没有形成两种不同的继承类别,而仅仅只是为了方便C++类方法的传递调用而设计的,其实在java这样面向对象要求更为严格的语言当中,没有实现继承,他必须通过委托方式来完成这一概念,如果熟悉java就会明白,如果一个对象要使用另外一个对象的接口功能,而自身又不能够充当该对象所扮演的角色时,就会通过委托来完成,这样一来就必须在对象中包含一个委托对象,通过对象调用语法来完成功能;在C++中就可以通过protected和private继承来完成java中的委托关系(当然C++也可以形成对象委托关系),那么这种情况下protected继承就容许委托可以传递(也就是被多级子类调用),而private继承是不容许委托被传递的。
区别就这些。

# re: C++类继承关系问题  回复  更多评论   

2007-05-31 15:33 by walkspeed
在面向对象的理论中有两种概念:接口、实现,所以就出现了所谓的接口继承和实现继承两种关系。而protected和private就是实现继承中所要用到的,其实protected和private两者则约束继承时并没有形成两种不同的继承类别,而仅仅只是为了方便C++类方法的传递调用而设计的。

这段话比较好。理解了接口继承和实现继承,对于C++很重要。
接口继承表明,继承类与父类有了一样的接口。
而实现继承,继承类和父类有不同的接口。

在C++中并没有将接口和实现那么明确的分离。所以大家很容易以为C++类中public部分的行为就是接口,其实对于面向对象的概念来说,C++类中public部分的行为并不是接口。

# re: C++类继承关系问题  回复  更多评论   

2007-06-04 14:16 by 看图软件
这是面向对象的基础

# re: C++类继承关系问题  回复  更多评论   

2007-06-07 10:25 by jazz
还有一种继承 virtual public继承,这个我一直不是很很明白.比如
class Usable;

class Usable_lock {
friend class Usable;
private:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};

class Usable : public virtual Usable_lock {
// ...
public:
Usable();
Usable(char*);
// ...
};

Usable a;

class DD : public Usable { };

DD dd; // error: DD::DD() cannot access
// Usable_lock::Usable_lock(): private member
这是c++作者关于模拟fianl功能的例子。

# re: C++类继承关系问题  回复  更多评论   

2007-06-07 10:38 by chemz
稍后我会写一篇关于虚继承和虚基类的文章,解释你所提到的问题。

# re: C++类继承关系问题  回复  更多评论   

2007-06-08 11:16 by jazz
谢谢 正关注着。。。

# re: C++类继承关系问题  回复  更多评论   

2007-10-11 17:13 by nothing
public 是is a
private 是 has a

protected应该算是什么呢?

virtual是保持只有一个基类实例

# re: C++类继承关系问题  回复  更多评论   

2007-10-12 08:44 by chemz
楼上提到:
public 是is a
private 是 has a

这个提法是OO概念发展的初期的一种认识,有点过于一般化不能更精确的表达出OO中的实际思想;一般现在的OO理论中将这样的概念称之为LSP(Liskov Substitution Principle),意思就是从行为上而言子类因该可以完全替换基类完成基类的行为职责。
public关键字在C++中仅仅只是一个语法元素,并不能强制使得采用了public继承的类体系一定满足LSP,其中还要看看子类在实现基类的接口行为时是否遵从了LSP原则,否则通过public继承而来的子类仍然不能称之为其满足LSP,当然此时可能能够满足is a关系。
至于has a关系在OO中应该理解为composite关系,也就是常说的组合关系,在其他的OO语言中(如:Java)composite仅仅能够通过包含关系来实现,在C++中则多了一种所谓的实现继承private,这样看来private仅仅只是一种特定语言的实现手段而已,代表的OO概念没有区别。
protected在继承时又应该是什么呢?其实如上面private具有相同的含义,仅仅只是为了方便C++类方法的传递调用而设计的,也是一种composite关系而已。
至于virtual继承关系请参看 http://www.cppblog.com/chemz/archive/2007/06/12/26135.html

# re: C++类继承关系问题  回复  更多评论   

2009-09-02 10:11 by erac
其实个人认为C++的protected、private的实现完全是为了设计模式方面的考虑,再加上基类无法限制子类的继承关系而进行的一种拓展。在Java中,final可以控制该类不能被继承,C++没有这种方式,但是private继承却可以限制继承类的继承类的访问控制。鉴于C++出现早于Java,个人认为C++标准的设计人员考虑的的确周到。不过个人觉得也没有必要非要记得哪种继承关系就是哪种什么接口继承和实现继承。

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理