构造函数

构造函数为什么不能是虚函数

只谈情不闲聊 提交于 2020-02-04 06:57:38
1. 从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。 2. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。 3. 构造函数不需要是虚函数,也不允许是虚函数,因为创建一个对象时我们总是要明确指定对象的类型,尽管我们可能通过实验室的基类的指针或引用去访问它但析构却不一定,我们往往通过基类的指针来销毁对象。这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。 4. 从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,也没有必要成为虚函数

Java基本概念

梦想的初衷 提交于 2020-02-04 05:44:05
问题及答案来源自《Java程序员面试笔试宝典》第四章 Java基础知识 4.1基本概念 1、J ava语言有何优势? 纯面向对象的语言 具有平台无关性,可移植性好 提供了很多内置的类库 提供了对web应用开发的支持 具有很好的安全性和健壮性 除去了C++中难以理解和容易混淆的特性(头文件、指针、多重继承等) 2、Java与C/C++有何区别? Java和C++的相同点: Java和C++都是面向对象语言,都使用了面向对象思想(例如封装、继承、多态等) 由于面向对象有许多非常好的特性(继承、组合等),因此二者都有很好的重用性 Java和C++的不同点: Java为解释性语言,而C/C++为编译型语言(Java执行速度比C/C++慢,但Java能跨平台执行而C/C++不能) Java代码运行过程:源代码通过Java编译器编译成字节码(.class),然后由JVM解释执行 C/C++代码运行过程:源代码通过编译和链接后生成可执行的二进制代码 Java为纯面向对象语言,所有代码要在类中实现,而C++兼具面向过程和面向对象编程的特点 Java没有C/C++中的指针 Java没有C++中的多重继承,但是Java引入了接口的概念,可以通过实现多个接口来实现与C++中多重继承一样的目的 在C++中需要开发人员管理内存分配(申请和释放),而Java中提供了垃圾回收器来实现垃圾的自动回收 C+

C++学习笔记12:赋值运算符‘=’的重载

一世执手 提交于 2020-02-04 03:07:46
1 目的:希望赋值运算符两边的类型可以不匹配 eg:将int类型变量赋值给一个Complex对象;或者吧一个char*类型的字符串赋值给一个字符串对象。 2 赋值运算符‘=’只能重载为成员函数 3 eg:(见本工程fuzhichongzai.cpp) /** * 赋值运算符‘=’重载例子 * */ # include <iostream> # include <cstring> using namespace std ; class String { private : char * str ; // 私有成员变量 str是一个指针,用来指向动态分配的存储空间,字符串就放在动态分配的存储空间 public : // 构造函数 new一个字符数组,只有一个元素,使得指针str指向new出来的存储空间 相当于 char* str = new char[1]; String ( ) //:str(new char[1]) { str = new char [ 1 ] ; str [ 0 ] = 0 ; // 初始化后str指向一个空字符串 cout << "调用无参构造函数" << endl ; } const char * c_str ( ) { return str ; } // 对赋值运算符进行重载,接收的参数是 const char* 返回值为String& String &

JS内置对象

二次信任 提交于 2020-02-04 02:36:55
JS内置对象 JavaScript中的三种对象:自定义对象、内置对象、浏览器对象 ECMAScript中的对象:自定义对象、内置对象 内置对象:内置对象就是系统提供的对象,已经存在的对象,例如Math、Array、Data… Math对象 Math对象不是构造函数,它具有数学常数和函数的属性和方法,都是以静态成员的方式提供跟数学相关的运算来找Math中的成员(求绝对值、取整) Data对象 Data实例用来处理日期和时间。Data对象基于1970年一月一日(世界标准时间)起的毫秒数 Math对象和Data对象的区别: Math 不是一个构造函数,里面提供的是静态成员 Data 是一个构造函数,首先要通过new Data () 来创建日期实例(对象),实例成员 Data()函数的使用方法 //日期构造函数 Data ( ) var d = new Data ( ) ; //1 空构造函数 获取的是当前时间对象 console. log ( d ) ; //距离1970-1-1相差的毫秒数 valueof ( ) 可以获取当前的毫秒数 console. log ( valueof ( ) ) ; //2 构造函数中传入毫秒数 var d = new Data ( 1502088177998 ) ; console. log ( d ) ; //3 可以传入日期形式的字符串 var d

C++ 初始化列表

╄→尐↘猪︶ㄣ 提交于 2020-02-03 22:48:01
类对象的构造顺序是这样的:   a.分配内存,调用构造函数时,隐式/显示的初始化各数据成员   b.进入构造函数后在构造函数中执行一般计算 1.初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内进行赋值操作。 使用初始化列表主要是基于性能问题. [参考 C++ 初始化列表 http://www.cnblogs.com/graphics/archive/2010/07/04/1770900.html。]   对于内置类型,如int, float等,使用初始化类表和在构造函数体内初始化差别不是很大,但是对于类类型来说,最好使用初始化列表,为什么呢?由上面的测试可知,使用初始化列表少了一次调用默认构造函数的过程,这对于数据密集型的类来说,是非常高效的。 2. 除了性能问题之外,有些时场合初始化列表是不可或缺的, 以下几种情况时必须使用初始化列表 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面 引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化。    如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表

Effective C++ 读书笔记(一)

半腔热情 提交于 2020-02-03 21:06:34
1 让自己习惯C++ 条款01:视C++为一个语言联邦 C++是多重范型编程语言,同时支持过程形式,面向对象形式,函数形式,泛型形式,元编程形式(什么是元编程?)的语言。 C++主要包括4部分:C, Object-Oriented C++, Template C++和STL。 条款02:尽量以const, enum, inline替换#define 1, 对于单纯变量最好以const 对象或enums 替换#defines. #define ASPECT_RATIO 1.653 const double ASPECT_RATION = 1.653; 常量定义式通常放在头文件中,若要在头文件内定义一个常量的char * -- based 字符串: const char * const autherName = “Scott Meyers”; Or const std::string autherName(“Scott Meyers”); Class专属常量: class GamePlayer{ Private: static const int NumTurns = 5; int scores[NumTures]; … }; Const int Gameplayer::NumTurns; class GamePlayer{ Private: static const int

确定对象被使用前已经被初始化

荒凉一梦 提交于 2020-02-03 20:51:55
在C part of C++中,声明一个变量,不一定会被初始化,而一旦进入non-C part of C++,规则有些变化。这就很好的解释了为什么array(来自C part of C++)不被初始化而vector却有此保证(来自STL of C++)。 表面上这似乎是个无法决定的状态,而最佳处理方法是:永远在使用对象前将它初始化。对于无任何成员的内置类型,你必须手工完成此事 int x = 0 ; const char * text = "A C-style string" ; double d ; std :: cin >> d ; 至于内置类型以外的任何其他东西,则需要构造函数来初始化。规则就是:确保每一个构造函数都将对象的每一个成员初始化。 这个规则很简单,但不要混淆了赋值和初始化。 class Money { public : Money (); private : int thecash ; } Money :: Money ( const int cash ) { thecash = cash ; //这是赋值,不是初始化 } Money :: Money ( const int cash ): thecash ( cash ) //这才是初始化 {} 第二个构造函数相比第一个,最终结果相同,但通常效率更高。第一个版本先调用默认构造函数设置初始值,然后再立刻对他们赋值

java之继承

僤鯓⒐⒋嵵緔 提交于 2020-02-03 13:04:16
封装 继承(Inheritance) 继承的作用:提高代码的复用性和可维护性 软件中,1000个对话框,每个对话框单独编写需要100行代码,总共需要10万行代码 考虑每个对话框共同的部分占70行,独有的占30行。70行代码编写一次,重复使用。 总共需要:70+30*1000=3万行 --如何编写代码实现继承? 字体对话框 段落对话框 使用子类通过extends继承父类 父类:超类、基类,superClass 子类:派生类,扩展类 Java中的继承,比C++要简单的多 C++支持多重继承(一个子类同时多个父类),Java不支持 继承的几个性质: (1)父类中的所有非私有成员都可以被子类继承(默认权限的成员,在包外不能被子类使用) (2)一般情况下,将需要被继承的成员定义为protected的 (3)被正常继承的成员,可以在子类中当成自己的成员使用 继承的特殊情况: (1)覆盖(重写override) 子类继承了父类的成员,万一子类中还定义了和父类相同类型和名称的成员,会不会有歧义? 子类中的成员会屏蔽掉父类成员,这叫做覆盖(Override) 注意:覆盖不允许使子类成员的访问权限比父类成员的访问权限严格 覆盖的作用?可保持子类的个性化 (2)父类和子类的关系 子类实例化时,系统会自动提前为该子类实例化父类对象 问题:父类构造函数万一有参数怎么办

TP里面使用Ajax方法

南笙酒味 提交于 2020-02-03 02:33:47
如果想要使用Ajax的话,因为Ajax是写在一个页面里面的,那么也就是说必须要先显示个页面出来,先显示一个静态的文件,然后我们可以在这个静态的文件里面写Jquery,通过Ajax 来调数据读数据。所以首先先做一个操作方法,这个操作方法来显示一个页面。 用下面这个方法来输出一下TP的所有常量的值 <?php namespace Home\Controller; use Think\Controller; class TestController extends Controller //如果不继承父类它就不是一个操作方法。 { public function index(){ var_dump(get_defined_constants(true)); } } 显示结果如下图: 如果这里面出现的常量没有出现双下划线的,只能是嵌在标记里面来用。(也就是定界符里面需要进行解析来使用) 有双下划线的直接用就行,不用写标记。 <?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function index(){ echo "欢迎使用ThinkPHP"; } public function ceshi(){ $this->show();

Java笔记(十三)……面向对象III继承(inheritance)

岁酱吖の 提交于 2020-02-02 15:55:16
继承概述 继承概述 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继那个类即可。 多个类可以称为子类,单独这个类称为父类或者超类。 子类可以直接访问父类中的非私有的属性和行为。 通过 extends 关键字让类与类之间产生继承关系。 class SubDemo extends Demo{} 继承好处 提高了代码的复用性。 让类与类之间产生了关系,有了这个关系,才有了多态的特性。 继承特点 Java只支持单继承,不支持多继承。 一个类只能有一个父类,不可以有多个父类。 class SubDemo extends Demo{} //ok class SubDemo extends Demo1,Demo2...//error Java支持多层继承(继承体系) class A{} class B extends A{} class C extends B{} 定义继承需要注意: 不要仅为了获取其他类中某个功能而去继承 类与类之间要有所属( " is a " )关系,xx1是xx2的一种。 super关键字 super和this的用法相像 this代表本类对象的引用 super代表父类的内存空间的标识。 当子父类出现同名成员时,可以用super进行区分 子类要调用父类构造函数时,可以使用super语句:super(); 函数覆盖