对于类以及类继承, 几个主要的问题:
1) 继承方式: public/protected/private继承. 这是c++搞的, 实际上继承方式是一种允许子类控制的思想. 子类通过public继承, 可以把基类真实还原, 而private继承则完全把基类屏蔽掉. 这种屏蔽是相对于对象层而言的, 就是说子类的对象完全看不到基类的方法, 如果继承方式是private的话, 即使方法在基类中为public的方法. 但继承方式并不影响垂直方向的访问特性,
比较(java): java是简化的, 其实可认为是c++中的public继承. 实在没必要搞private/protected继承, 因为如果想控制,就直接在基类控制就好了.
2)
假设 class C :
则初始化的顺序是A, B, D, C的构造函数. 这里基类的初始化顺序是按照声明的顺序, 成员对象也是按照声明的顺序. 因此 c(int i, int j) : B(i), A(j) {} //这里成员初始化列表的顺序是不起作用的
析构函数的顺序则刚好是调过来, 构造/析构顺序可看作是一种栈的顺序
比较(java): java中初始化赋值是一回事. 而且对基类的构造函数调用必须显示声明, 按照你自己写的顺序. 对成员对象, 也叫由你初始化. 没有什么系统安排的顺序问题, 让你感觉很舒服
3) 多继承问题: c++支持多继承, 会导致"根"不唯一. 而java则没有该问题; 此外c++没有统一的root object, java所有对象都存在Object类使得很多东西很方便. 比如公共的seriall, persistent等等.
4) 继承中的重载:
比较(java): java中则不管, 就算有新增对象基类函数没有考虑到, 大不了就是null, 或者你自己有缺省值. 也是合理的.
5) 继承中的同名覆盖和二义性: 同名覆盖的意思是说, 当派生类跟基类有完全一样的成员变量或者函数的时候, 派生类的会覆盖基类的. 类似于同名的局部变量覆盖全局变量一样. 但被覆盖的基类成员还是可以访问的.
如B继承A, A, B都有成员变量a,则B b, b.a为访问B的a, b.A::a则为访问基类中的a. 这对于成员函数也成立. 但需要注意的是, 同名函数必须要完全一样才能覆盖. int func(int j)跟int func(long j)其实是不一样的. 如果基类,派生类有这两个函数, 则不会同名覆盖. 最重要的是, 两者也不构成重载函数. 因此加入A有函数int func(int j), B有函数int func(long j). 则B的对象b.func(int)调用为错误的. 因为B中的func跟它根本就不构成重载.
另外一个导致二义性的是多重继承. 假设B1, B2都继承自B, D则继承B1, B2. 那么D有两个B而产生二义性.
这种情况的解决办法是用虚基类. class B1 : virtual public B, class B2:virtual public B,
D则为class D : public B1, public B2. 这样D中的成员只包含一份B的成员使得不会产生二义性.
比较(java). java中是直接覆盖. 不给机会这么复杂, 还要保存基类同名的东西. 同名的就直接覆盖, 没有同名的就直接继承.