您的位置:首页 > 编程语言 > Java开发

JAVA 变量默认值问题

2009-12-02 10:54 253 查看
  中心提示:虚函数必须是类的非静态成员函数(且非构造函数), 其访问权限是public(可以定义为privateorproteceted, 但是关于多态来说, 没有意义。 在基类的类定义中定义虚函数的普通形式  虚函数的定义:  虚函数必须是类的非静态成员函数(且非构造函数), 但是关于多态来说, 没有意义。 ), 在基类的类定义中定义虚函数的普通形式:  virtual函数返回值类型虚函数名(形参表)  虚函数的作用是完成静态联编, 在定义了虚函数后, 在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。 以完成统一的接口, 不同定义过程。 如果在派生类中没有对虚函数重新定义, 则它承继其基类的虚函数。 当顺序发现虚函数名前的关键字virtual后, 会自动将其作为静态联编处理, 即在顺序运转时静态地选择合适的成员函数。   2、类之间存在子类型关系, 普通表现为一个类从另一个类私有派生而来。   定义虚函数的限制:  ??)非类的成员函数不能定义为虚函数, 类的成员函数中静态成员函数和构造函数也不能定义为虚函数, 但可以将析构函数定义为虚函数。 优秀的顺序员经常把基类的析构函数定义为虚函数。 因为, 将基类的析构函数定义为虚函数后, 系统会调用相应的类的析构函数。 而不将析构函数定义为虚函数时,   ?而定义函数时不需求使用关键字“virtual”。   ?则在该类中不能出现和这个成员函数同名并且返回值、参数个数、参数类型都相同的非虚函数。 也不能出现这种非虚的同名同返回值同参数个数同参数类型函数。   为什么虚函数必须是类的成员函数:  虚函数诞生的目的就是为了完成多态, 在类外定义虚函数毫无实际用途。   为什么类的静态成员函数不能为虚函数:  如果定义为虚函数, 那么它就是静态绑定的,   为什么构造函数不能为虚函数:  因为如果构造函数为虚函数的话, 它将在执行期间被构造, 而执行期则需求对象已经树立, 构造函数所完成的任务就是为了树立合适的对象, 在承继体系中, 构造的顺序就是从基类到派生类, 其目的就在于确保对象能够成功地构建。 构造函数同时承当着虚函数表的树立, 如何确保vtbl的构建成功呢?  留意:当基类的构造函数外部有虚函数时, 又如何任务呢?与构造函数相同, 只要“局部”的版本被调用。 行为相同, 构造函数只能调用“局部”版本, 我们知道, 析构函数的调用顺序与构造函数相反, 当某个类的析构函数被调用时, 其派生类的析构函数已经被调用了, 相应的数据也已被丢失, 如果再调用虚函数的派生类的版本, 就相当于对一些不牢靠的数据停止操作, 这是十分危险的。 因此, 虚函数机制也是不起作用的。   C++中的虚函数的作用主要是完成了多态的机制。 关于多态, 简而言之就是用父类型别的指针指向其子类的实例, 然后经过父类的指针调用实际子类的成员函数。 这种技术可以让父类的指针有“多种外形”, 这是一种泛型技术。 虚函数技术,   关于虚函数的使用方法, 我在这里不做过多的论述。 大家可以看看相关的  C++的书籍。 在这篇文章中,   当然, 相同的文章在网上也出现过一些了, 没有比拟, 没有举一反三。 也希望大家多给我提意见。 让我们一同进入虚函数的世界。   虚函数表  对C++了解的人都应该知道虚函数(VirtualFunction)是经过一张虚函数表(VirtualTable)来完成的。 主是要一个类的虚函数的地址表, )中这个表被分配在了这个实例的内存中(注:一个类的虚函数表是静态的, 他的虚函数表的是固定的, 不会为每个实例生成一个相应的虚函数表。 所以, 当我们用父类的指针来操作一个子类的时分, 这张虚函数表就显得由为重要了, 它就像一个地图一样,   假定我们有这样的一个类:  依照下面的说法, 我们可以经过Base的实例来得到Base的虚函数表。 我们可以经过强行把&b转成int, 取得虚函数表的地址, 然后, 也就是Base::f(), 这在下面的顺序中得到了验证(把int强迫转成了函数指针)。 经过这个示例, 如下所示:  留意:在下面这个图中, 我在虚函数表的最后多加了一个结点, 这是虚函数表的完毕结点, 就像字符串的完毕符“\0”一样, 其标志了虚函数表的完毕。 这个完毕标志的值在不同的编译器下是不同的。 我将区分说明“无覆盖”和“有覆盖”时的子类虚函数表的样子。 我之所以要讲述没有覆盖的情况, 主要目的是为了给一个对比。   普通承继(无虚函数覆盖)  下面, 再让我们来看看承继时的虚函数表是什么样的。 假定有如下所示的一个承继关系:  请留意, 在这个承继关系中, 子类没有重写任何父类的函数。 重载就是所谓的名同而签名不同, 重写就是对子类对虚函数的重新完成。 )  我们可以看到下面几点:  1)虚函数依照其声明顺序放于表中。   普通承继(有虚函数覆盖)  覆盖父类的虚函数是很显然的事情, 不然, 如果子类中有虚函数重载了父类的虚函数,   为了让大家看到被承继过后的效果, 那么, 关于派生类的实例的虚函数表会是下面的样子:  我们从表中可以看到下面几点,   2)没有被覆盖的函数照旧。   由b所指的内存中的虚函数表(子类的虚函数表)的f()的位置已经被Derive::f()函数地址所取代, 于是在实际调用发作时, 这就完成了多态。 再让我们来看看多重承继中的情况,   关于子类实例中的虚函数表,   2)子类的成员函数被放到了第一个父类的表中。 而能够调用到实际的函数。   多重承继(有虚函数覆盖)  下面我们再来看看,   我们可以看见, 三个父类虚函数表中的f()的位置被交流成了子类的函数指针。 我们就可以用任一个父类指针来指向子类, 并调用子类的f()了。 如:  安全性  每次写C++的文章, 这篇文章也不例外。 相信我们对虚函数表有一个比拟细致的了解了。 水可载舟, 亦可覆舟。 下面, 让我们来看看我们可以用虚函数表来干点什么好事吧。 子类没有重载父类的虚函数是一件毫无意义的事情。 因为多态也是要基于函数重载的。 虽然在下面的图中我们可以看到子类的虚表中有Derive本人的虚函数, 所以, 这样的顺序根本无法编译经过。   但在运转时, 但这些非public的虚函数同样会存在于子类虚函数表中,   如:  完毕语  C++这门语言是一门Magic的语言, 关于顺序员来说, 我们似乎永远摸不清楚这门语言背着我们在干了什么。 需求熟悉这门语言, 需求去了解C++中那些危险的东西。 不然, 这是一种搬起石头砸本人脚的编程语言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: