protected:可以被
public:可以被
第二:类的继承后方法属性变化。
使用private继承,父类的protected和public属性在子类中变为private;
使用protected继承,父类的protected和public属性在子类中变为protected;
使用public继承,父类中的protected和public属性不发生改变;
public继承 public protected 不可用
protected继承 protected protected 不可用
private继承 private private 不可用
protected继承和private继承能降低访问权限。
对于公有继续方式:
(1) 基类成员对其对象的可见性:
公有成员可见,其他不可见。这里保护成员同于私有成员。
(2) 基类成员对派生类的可见性:
公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。
(3) 基类成员对派生类对象的可见性:
公有成员可见,其他成员不可见。
所以,在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。这里,一定要区分清楚派生类的对象和派生类中的成员函数对基类的访问是不同的。
对于私有继续方式:
(1) 基类成员对其对象的可见性:
公有成员可见,其他成员不可见。
(2) 基类成员对派生类的可见性:
公有成员和保护成员是可见的,而私有成员是不可见的。
(3) 基类成员对派生类对象的可见性:
所有成员都是不可见的。
所以,在私有继续时,基类的成员只能由直接派生类访问,而无法再往下继续。
对于保护继续方式:
这种继续方式与私有继续方式的情况相同。两者的区别仅在于对派生类的成员而言,对基类成员有不同的可见性。
上述所说的可见性也就是可访问性。关于可访问性还有另的一种说法。这种规则中,称派生类的对象对基类访问为水平访问,称派生类的派生类对基类的访问为垂直访问。
一般规则如下:
公有继续时,水平访问和垂直访问对基类中的公有成员不受限制;
私有继续时,水平访问和垂直访问对基类中的公有成员也不能访问;
保护继续时,对于垂直访问同于公有继续,对于水平访问同于私有继续。
对于基类中的私有成员,只能被基类中的成员函数和友元函数所访问,不能被其他的函数访问。
基类与派生类的关系
任何一个类都可以派生出一个新类,派生类也可以再派生出新类,因此,基类和派生类是相对而言的。
基类与派生类之间的关系可以有如下几种描述:
1. 派生类是基类的具体化
类的层次通常反映了客观世界中某种真实的模型。在这种情况下,不难看出:基类是对若干个派生类的抽象,而派生类是基类的具体化。基类抽取了它的派生类的公共特征,而派生类通过增加行为将抽象类变为某种有用的类型。
2. 派生类是基类定义的延续
先定义一个抽象基类,该基类中有些操作并未实现。然后定义非抽象的派生类,实现抽象基类中定义的操作。例如,虚函数就属此类情况。这时,派生类是抽象的基类的实现,即可看成是基类定义的延续。这也是派生类的一种常用方法。
3. 派生类是基类的组合
在多继续时,一个派生类有多于一个的基类,这时派生类将是所有基类行为的组合。
派生类将其本身与基类区别开来的方法是添加数据成员和成员函数。因此,继续的机制将使得在创建新类时,只需说明新类与已有类的区别,从而大量原有的程序代码都可以复用,所以有人称类是“可复用的软件构件”
二、各个变量在类加载的时候的初始化顺序
public class StaticTest{
public static void main(String args[]){
staticFunction();
}
static StaticTest st = new StaticTest();
static{
System.out.println("1");
}
StaticTest(){
System.out.println("3");
System.out.println("a="+a+" b="+b);
}
public static void staticFunction(){
System.out.println("4");
}
{
System.out.println("2");
}
int a=100;
static int b=112;
}
我们先来看一下各个变量在类加载的时候的初始化顺序:
1、初始化父类的静态变量,静态代码块,初始化的顺序按照出现顺序。
2、初始化子类的静态变量,静态代码块。
3、初始化父类的成员变量。
4、执行父类的构造函数。
5、初始化子类的成员变量。
6、构造代码块创建对象时执行。
7、执行子类的构造函数。
执行的结果为:
2
3
a=100,b=0
1
4
产生这个结果的原因的关键在这一句话:
static StaticTest st = new StaticTest();
st变量的引用是本类的实例,因此在实例化st变量时,将实例初始化嵌入到静态初始化中。因为这一句放在静态初始化的开头,所以static int b=112没有被调用,输出的b=0,同时,输出1也在2和3后面。在对象的初始化时,也是先初始化环境变量,再执行构造函数,a的值为100。
静态数据成员
假如我们要设计一个战争游戏,游戏中有许多的兵种。游戏的过程中,每隔一段时间每个兵种都会产生,同时由于战争的消耗,每个兵种士兵的数量又会减少。为了情节更逼真呐,我们引入了一个士气的概念,当士气比较高的时候,这个兵种的士气战斗力就会很强,士气较低的时候,兵种的战斗力就会比较弱。兵种的士气受很多因素影响,其中一个最直接的因素就是士兵的数量相关,它与数量成正比。我们就需要一组全局变量,每个变量都会记录当前兵种的数量,但是使用全局变量会引入很多的问题,使用全局变量的安全得不到保障,我们可以在程序的任何地方修改它的值。全局变量还可能导致命名空间的污染,当程序比较大的时候,各个模块之间有可能冲突。那如果不使用全局变量,我们就可以使用静态的数据成员。
静态数据成员:以static开头。静态数据成员为各个对象共有,不属于某个具体的对象,所有对象都可以对它进行引用,都可以读取和修改。若一个对象修改了该静态成员的值,则在其他各个对象中该数据成员的值都会同时改变。
定义类时就为静态数据成员分配空间,不随对象的建立而分配空间。可以说它是属于这个类的,定义完类之后就可以引用。
1.定义方法
static int count;//定义了一个int类型的静态数据成员,它的定义是在类里面,但是初始化不可以在类的里面类外面初始化 (你可以在类的实现文件里面初始化): int CTime::count=0;//初始化不要再加static
2.调用方法
1)类名::静态成员
2)对象名.静态成员
在类内的静态数据成员仅仅是对该成员的声明,同时还需要在类外部进行定义。
当我们在构造函数里面对它++然后输出,在析构函数里面—输出就得到这样的结果:构造函数调用的次数就是创建对象的个数,析构函数调用的次数就是销毁对象的次数。
静态成员函数
在声明成员函数时在函数前添加static关键字就定义了静态成员函数。
与静态数据成员一样,静态成员函数也是类的一部分。
1.声明静态成员函数
static int func(); //定义的时候不需要static关键字
2.调用静态成员函数
1)类名::静态成员函数
2)对象名.静态成员函数
静态成员函数一般是为了处理静态的数据成员。
与一般成员函数的区别:
1)非静态成员函数有this指针,静态成员函数没有this指针。