`
lilisalo
  • 浏览: 1105700 次
文章分类
社区版块
存档分类
最新评论

Java 走向C++

 
阅读更多

本文不涉及一些微妙蛋疼的语法比较, 关注的是宏观方面, 当然后期逐步更新如果, 如果觉得必要, 可能会加上.


议题之一: 初始化的比较

1.CPP基类的任何类构造函数会默认调用父类的不带参数的构造函数, 这点Java也是同样处理的. 子类调用父类的构造函数方式会不同, C++中这样做:

Son::Son(int id):Father(id) {

//Father(10); //注意,这样虽然编译通过,但事实上在构造一个Father类,完了( 出了作用域)之后就立即销毁. 危害非常之大.

cout<<"in Sonconstructor Son(int id) function!"<<endl;

}

2.Son son 这样的方式初始化, 会将一个对象初始化在栈上, 当超出作用域, 自动消除. Son *son这样的方式初始化, 会将一个对象放在堆上, 需要手动Delete, 否则内存泄漏. Son* pSon这样的方式, 没有构造任何对象.

3.上面也意味着, 除基本类型外, Java的对象都是在堆中分配的.

4.构造和析构的基本顺序是《看源代码》:

  1. $./app.exe
  2. InMainFunction!
  3. inFatherItemconstructorFatherItem()function!
  4. infatherconstructorFather(intid)function!
  5. inSonItemconstructorSonItem()function!
  6. inSonconstructorSon(intid)function!
  7. inSondestructor~Son()function!
  8. inSonItemdestructor~SonItem()function!
  9. inFatherdestructor~Father()function!
  10. inFatherItemdestructor~FatherItem()function!

上面是子类调用父类带参数函数的例子, 基本说明的情况是:

a.父类的成员变量初始化

b.父类的构造函数初始化(看子类调用那个父类的构造函数,默认情况是不带参数的)

c.子类的.h文件中声明的成员变量初始化

d.子类的构造函数调用

析构的顺序正好相反.

这跟Java实质上是一致的, 微弱的区别在于语法表达不同:注意C++引起成员变量的调用, 要么是Son son, 要么是Son* pSon = new Son(); 类似于Son* pSon是没有做初始化的. 不会引起构造函数的调用;而Java中持有的都是引用. 这点需要特别关注, Java中的Son son = new Son()类似于Son* pSon = new Son();(Java中的Son son类似于C++中的Son*pson, 没有做初始化工作). 参见2.

5.关于静态成员变量.

a.Java的静态成员变量在类加载的时候就完成. 类加载是指, 类的首次使用,比如类被构造, 类的其他静态函数或者成员被使用. 因此他会先于所有的成员被初始化. 子类的static成员初始化之前,会先初始化父类的static成员变量, 当静态成员初始化完成之后, 然后参考4的顺序.

b.C++的静态成员变量.

在C++中, 声明静态成员函数是放在.h文件中:

  1. public:
  2. staticvoidstatic_function();//静态成员函数
  3. private:
  4. FatherItemitemOne;
  5. FatherItemstaticstatic_fatherWithPara;

将成员变量初始化是放在cpp文件中, 注意跟类定义是类似的:

void Father::static_function() {

// TODO Auto-generated destructor stub

cout<<"in Fatherstatic_function function!"<<endl;

}

FatherItem Father::static_fatherWithPara(10);

当然,结论跟Java是一致的,也即, 类首次加载的时候,完成静态变量的初始化, 加载子类前,首先父类务必先加载. 当类加载成功之后, 在考虑普通变量的初始化,以及构造函数的调用.

6.C++的普通成员初始化.

.h文件中的声明的普通对象被初始化, 比如下面这个:

private:

FatherItem fatherIt;

声明的时候, 先初始化fatherIt, 然后构造函数被调用。跟4的解释一致。但这里就会引申出另外一个问题, 带参数的变量声明,会发生什么, 比如:

private:

FatherItem father(1);

这里要务必注意,这是一个语法错误. 源于声明中存在的二义性问题, 因为我们声明函数也是这么声明的:

private:

ReturnValue FunctionName(Parameter name);

这样编译器看到这个就懵了. 为了清晰起见,我们把这样的声明,还是留给了函数.我们只在头文件中声明变量, 然后在构造函数的外部去定义/初始化这个变量:

在头文件中:

  1. private:
  2. FatherItemfatherWithPara;

在.cpp文件的构造函数中:

  1. Father::Father():fatherWithPara(10){
  2. cout<<"infatherconstructorFather()function!begin"<<endl;
  3. cout<<"infatherconstructorFather()function!end"<<endl;
  4. }

这样会带来一个弱点,会发生我们不愿意看到的情况,就是.h中声明的变量,实质上已经被它的默认(即不带参数的)构造函数初始化了, 然后我们在构造函数外部,有对这个变量初始化一次.

——很幸运,这个推断是错误的,结论是: 构造函数外初始化的变量, 在.h中不会被初始化. 也就是说,仅仅初始化一次. 先看我们的测试,马上就可以论证这个结论.

做一个如下的测试,彻底看看对象的初始化过程:

声明两个变量,一个带参数,一个不带参数,这个在头文件中:

  1. private:
  2. FatherItemitemOne;
  3. FatherItemfatherWithPara;
然后在构造函数中初始化fatherWithPara, 但不初始化itemOne, .cpp的代码如下:

  1. Father::Father():fatherWithPara(10){
  2. cout<<"infatherconstructorFather()function!begin"<<endl;
  3. cout<<"infatherconstructorFather()function!end"<<endl;

运行代码可以发现,顺序如下:

$ ./app.exe

In Main Function!

in FatherItem constructor FatherItem() function!//头文件的声明产生的调用

in Constructor FatherItem(int i)function! 10 //构造函数外调用

in father constructor Father() function! Begin //构造函数调用

in father constructor Father() function! End

in Father destructor ~Father() function!

in FatherItem destructor ~FatherItem()function!

in FatherItem destructor ~FatherItem()function!

进一步搞定这个问题的方案是: 即使我们.h文件中的变量声明过了, 我们依然在构造函数的外部, 进行再次初始化:

不难发现, .h文件中声明的变量,如果在构造函数外部被初始化了, 则声明中不会再次初始化.

7.有必要总结一下整个初始化,流程,结合4,5和6. 为描述方便, 假如Son son出现在Main函数中, 即son对象需要被初始化:

A.初始化静态变量, 按照先父(Father类)后子(Son类)的顺序:

1.加载静态变量所在的类

2.加载类同时, 立即初始化该类的所有静态成员变量.

B.按照先父(Father类)后子(Son类)的顺序, 完成以下操作, 注意下面是对一个类进行的操作.

1.初始化类的.h文件中声明的变量(并满足在构造函数外没有被初始化). 调用的是默认构造函数(即不带参数的). 如果在构造函数外出现了成员变量的, .h文件中的变量无需初始化.

2.调用构造函数外所列出的所有成员变量名称涉及的构造方法.

3.调用类的构造函数.

8.有必要约定的规则:

a..h中永远只做声明, 声明了任何变量, 务必在构造函数的外部进行初始化, 即使是不带参数的变量.

b..cpp中永远只做定义.

c.摒弃一切奇技淫巧. 比如今天看到的.h中的声明, 变成定义这样的问题.

附上源码:

源码地址

源码说明:

1. 包含Java和CPP的源代码. 理论上两者都是跨平台的. CPP的是用GCC编译器, 当然用VS肯定是没有问题

2. 主要成员说明: Father类, 持有成员变量FatherItem.

3 Son类, 持有成员变量SonItem

4 Father 和 son是继承关系

5. SonItem和FatherItem没有任何关系.


议题之二: 数据管理

我的个人偏见是,内存管理,实质上是数据管理. 后期展开该话题.

函数参数传递, 全局变量的管理模式, 成员变量的设计思想.

议题之三: 第三方代码的引入或者导出

源码的引入, 比如java会采用import, C++会采用include, using namespace的方式

二进制代码模块的引入, java会引入jar包. C++会引入静态库, 共享库/动态库等.

http://blog.csdn.net/ostrichmyself/article/details/6035538
分享到:
评论

相关推荐

    C++插件平台库设计文档

    基于插件开发在Java领域比较普遍,但是在C++方面却比较少见;而C++插件平台库(简称插件平台库或插件平台)就是面向C++开发人员的插件式平台。 插件平台的目标是减少学习成本、降低开发难度、提高开发效率、增强系统...

    java算法大全

    · 探索使用C、C++、Java以及Ruby实现的算法解决方案以及开发小贴士。 · 了解算法预期的性能,以及它达到最高性能时所需要的条件。 · 发现不同算法之间相似的设计哲学。 · 学习高级数据结构,来提升算法的性能...

    计算机程序的正确定义

    程序不是医治百病的灵丹妙药,在它走向反面的时候,它是使那些官僚主义者和视劳苦大众利益如不见的人们推脱掉自己应当承担的责任的最好的挡箭牌。因为越是严密完善的程序,按部就班执行起来越是要付出时间的代价,当...

    怎样走向成功之路--谭浩强

    怎样走向成功之路--谭浩强该文是谭浩强所做的报告,谭浩强是何去人也,估计学计算机的都知道吧,看看这位老人是怎么谈他是怎么走向成功的,一定对你很有帮助的。

    菠菜源码JAVA-clojure-learning-notes:Clojure学习笔记

    Java相对C、C++来说有明显的优势,可以说是一种更高级的语言,高级语言带来的优势是能用更少的代码写出同样的功能,代码更接近与人的表达。 Java依然是现在业界最流行的开发语言,但这并不意味着Java能够一直的辉煌...

    Technology radar 2010

    对2010年所有软件开发的技术、工具、语言、平台做出了详尽的分析,对未来的走向也有一个很...想了解我们最关注的语言,如java c++ .net js as等语言,linux windows等平台的未来走向,请认真阅读此书。 本书为英文版。

    算法技术手册 - 中文版

     · 探索使用C、C++、Java以及Ruby实现的算法解决方案以及开发小贴士  · 了解算法预期的性能,以及它达到最高性能时所需要的条件  · 发现不同算法之间相似的设计哲学  · 学习高级数据结构,来提升算法的性能 ...

    算法技术手册.[美]George T.Heineman(带详细书签)

    · 探索使用C、C++、Java以及Ruby实现的算法解决方案以及开发小贴士 · 了解算法预期的性能,以及它达到最高性能时所需要的条件 · 发现不同算法之间相似的设计哲学 · 学习高级数据结构,来提升算法的性能 通过...

    算法技术手册(epub)

    · 探索使用C、C++、Java以及Ruby实现的算法解决方案以及开发小贴士 · 了解算法预期的性能,以及它达到最高性能时所需要的条件 · 发现不同算法之间相似的设计哲学 · 学习高级数据结构,来提升算法的性能 通过...

    算法技术手册.azw3

    · 探索使用C、C++、Java以及Ruby实现的算法解决方案以及开发小贴士 · 了解算法预期的性能,以及它达到最高性能时所需要的条件 · 发现不同算法之间相似的设计哲学 · 学习高级数据结构,来提升算法的性能 通过...

    算法技术手册(中、英文版)(George T. Heineman等著,杨晨、李明 译)

    · 探索使用C、C++、Java以及Ruby实现的算法解决方案以及开发小贴士 · 了解算法预期的性能,以及它达到最高性能时所需要的条件 · 发现不同算法之间相似的设计哲学 · 学习高级数据结构,来提升算法的性能 通过...

    人工智能项目资料-电子宠物中负责开发的交互app.zip

    电子宠物中负责开发的交互app,功能包括:蓝牙通信、wifi视频实时传输(依赖于深圳市瑞科慧联科技有限公司提供的sdk)、基于opencv的图像识别(c++与java混编)。 【探索人工智能的宝藏之地】 无论您是计算机相关...

    程序员需要经常刷题吗-object-calisthenics:我们入职体验的第一天

    Java、Javascript、Scala、Ruby、Groovy、Python、Smalltalk、C++、Self 和 Common Lisp 等语言。 为什么 遵循这里给出的规则和纪律将迫使您想出更难的答案,从而对面向对象编程有更丰富的理解。 如果您按照所有这些...

    XML高级编程

    用于XML的工具已经有了Perl、C++、Java、JavaScript和任何支持COM的语言版本。Microsoft Internet Explorer(主要是5.0或更新的版本)拥有很强的XML内置功能,而Mozilla浏览器也有类似的支持。XML工具还深入到了主要...

    vb 专门人才管理系统 论文 完整版

    对于大中型企业来说,利用计算机支持企业高效率完成劳动人才管理的日常才务,是适应现代企业制度要求、推动企业劳动人才管理走向科学化、规范化的必要条件;计算机管理所无法比拟的优点检索迅速、查找方便、可靠性高...

    基于SSH的医院在线挂号

    互联网技术已走向科技发展的巅峰期,我们要做的就是合理的使用互联网技术让我们的各个行业得到更快速的发展。 就医疗领域来说,如今看病难已成为我们生活中的一大难题,传统的医院挂号中,我们需要用手动方式来处理...

    asp.net知识库

    C++ 泛型编程系列讲座之实施 泛型技巧系列:简单类型选择器 C# 泛型简介 我眼中的C#2.0新功能特性 泛型技巧系列:避免基类及接口约束 New Article 不该用Generics实现Abstract Factory的理由 C#2.0-泛型 C#2.0-...

Global site tag (gtag.js) - Google Analytics