面向对象程序设计作为一种重要的程序设计思想,在近些年来得到广泛的推崇。而Java和C++更是面向对象程序设计语言中的翘楚,要彻底摸清面向对象程序设计的精髓和在实际应用中更加高效的进行代码设计,我们有必要对比一下Java和C++的在实现面向对象程序设计上的异同之处,对两种语言的细节之处做一个详尽的了解。
    面向对象程序设计概念:
    面向对象编程技术并不是简单的替代了结构化编程技术,而是在结构化编程的基础上做了一个很大的提升。很多面向对象技术仍然是建立在结构化编程技术之上。这里有一个很明显的是函数指针和面向对象中的多态之间的关系。并且今天所谓鼓吹java等语言是完全的面向对象语言者,其实完全忽略了其面向过程的一面。一个很显然的反例就是java中依然存在非对象的基本数据类型。面向对象编程为程序员提供了良好的封装形式,使得用户只需关心对象对外提供的数据和功能而不用去关心对象的具体实现。
    结构化程序设计中,核心考虑的是处理流程,然后是在流程中考虑如何保存与访问所需处理的数据,将数据和处理分开来看。这也就是Pascal语言的发明者Niklaus Wirth 在他的一本书中提到的公式Algorithms + Data Structures = Programs.而在面向对象的程序设计中,核心考虑的是对象,对象包含了数据并提供了处理功能,实现了数据和处理的更好的结合。当数据集合很小的时候,用面向过程语言来处理并不是一个很困难的问题。但当面临大规模的程序设计问题时,面向过程的实现方式显然就力不从心了。这时,面向对象编程就显示了它强大的威力。在面向对象程序设计时,数据和处理按照相关性被分解到各个对象中,每个对象只访问和处理本对象所包含的数据,这样就大大降低了程序设计的复杂度。下面我们用一句话来总结面向对象程序设计和面向过程的程序设计的特点:面向过程/结构化编程是大面积紧耦合的,而面向对象编程是小面积紧耦合(对象内部)和大面积松耦合的(对象之间).
 
   2.       类和对象的概念:
    一个形象的比喻是类是模板或蓝图而对象是实际物体。相当与在建筑设计中类是图纸而对象就是高楼大厦,所以说对象是类的一个实例!java提供了良好的封装机制,我们只有正确的使用好这些封装机制才能正确的发挥其作用。避免通过外部方法来直接访问类的字段,而是用类的方法来间接访问类的字段,这是实现数据封装的必有之路,而java严格的实现了这一点,但C++可以通过友员函数等机制来破坏这个性质,所以java是比C++更面向对象化的语言。
    面向对象的程序设计中需要把握一个对象的下面三个特征:
    a). 对象的行为(behavior): 可以使用这个对象来做些什么?或用这个对象可以调用哪些方法?
    b). 对象的状态(state): 当执行上述的方法时对象会作何反应?
    c). 对象的身份(identity): 当遇到和这个对象具有相同行为和相同状态的对象时,如何进行对象身份的识别?
    一个类的所有实例对象共享相同的一组行为特征,即这些对象实现了相同的方法。上面这三个特征是相互作用和相互影响的。 
    类之间的关系:
    a). 相关(dependence) ("uses-a"): 如果一个类中有成员函数的参数使用了另外一个类的对象,我们就说这两个类是相关的。在实际的编程中应当尽量减少这种类之间的相关关系,一个重要的理由是当类A中使用了类B的对象时,当B类做了改变时A类必须做出相应的改变。一个哲学意义上的说法是如果A意识不到B的存在,那么B的任何变化对A来说都是毫无意义的。
    b). 聚合(aggregation) ("has-a"): 以后详述;
    c). 继承(inheritance) ("is-a"):以后详述;

3.    Java中的对象变量和C++中对象指针的关系:

Java中的对象变量实际上类似与C++中的对象指针,Java中的对象变量实质上就是指向对象的对象指针,在对象变量变量中保存的是对象在内存中的实际地址.

因此,Java中两个对象的赋值不能用=,因为=号只是将两个变量指向同一个对象在内存中的地址。因此在这两个对象之间进行==比较时也只是比较这两个变量是否指向的是内存中的同一个对象,并不是比较两个对象的值是否相等!要比较两个对象是否相等,则需要使用equals方法!

因此在Java的类中的类访问器中不能直接返回一个可改变对象的引用,下面的代码说明了这一点:

import java.util.*;
publicclass EmployeeTest{  
   public static void main(String[] args)
   {  
      Employee harry = new Employee("Harry Brown",,,,);
      Date d = harry.getHireDay();       System.out.println(d);       double tenYearsInMilliSeconds = *365.35****;
      d.setTime(d.getTime()-(long)tenYearsInMilliSeconds);       System.out.println(harry.getHireDay());
   }
} class Employee
{  
   public Employee(String n, double s, 
      int year, int month, int day)
   {  
      name = n;
      salary = s;
      GregorianCalendar calendar
         = new GregorianCalendar(year, month - , day);
         // GregorianCalendar uses 0 for January
      hireDay = calendar.getTime();
   }    public String getName()
   {  
      return name;
   }    public double getSalary()
   {  
      return salary;
   }    public Date getHireDay()
   {  
      return hireDay;
   }    public void raiseSalary(double byPercent)
   {  
      double raise = salary * byPercent / ;
      salary += raise;
   }    private String name;
   private double salary;
   private Date hireDay;
}
结果: 

Wed Feb 03 00:00:00 CST 2010

Wed Feb 02 12:00:00 CST 2000 

这段代码的main函数中返回了一个可改变对象的引用,那么这个引用和这个可改变对象指向了同一块的内存对象,那么通过这个引用就可以修改这个内存对象!因此,这种所谓的“访问器”实际上破坏了封装性,解决方法是在返回可改变对象时先clone一个这个对象的副本,然后返回这个副本的引用。这样所有对这个返回引用的操作都执行在这个副本上,原来的对象并没改变:

public Date getHireDay()

{

return (Date)hireDay.clone();

}

结果:

Wed Feb 03 00:00:00 CST 2010
Wed Feb 03 00:00:00 CST 2010

4 . Java 和 C++ 在对象构造方面的差异:
Java中的实例域可以进行显示初始化,而C++中的数据域是不能显示初始化的!但C++在构造函数中可以提供一个数据域初始化列表!


Java代码:

public class TestConstruct
{
    public static void main(String[] args)
    {
        TestConstruct tc = new TestConstruct();
        System.out.println(tc.GetName());    
    }
    public String GetName()
    {
        return name;
    }
    private String name = "Jim Green";
}

输出结果:

Jim Green

C++ 代码:

#include <iostream>#include <string>

using namespace std;

class Person
{
    public:
        Person(String& aname)
        {
            name = aname;
        }
    private:
        string name = "Miracle Jiang";
} int main(void)
{     return ;
}

输出结果:

TestConstruct.cc::: warning: non-static data member initializers only available with -std=c++ or -std=gnu++ [enabled by default]
   string name = "Miracle Jiang";
上述结果C++11之前是不支持“显示实例域初始化”的,C++11之后可以使用了。但为了代码兼容性,最好不要使用这个性质。

Java 类中的构造函数之间可以相互调用,可以将公共构造部分放到一个构造函数中,其他特殊构造函数共同调用这个公共构造函数,使用this(...),C++中的构造函数之间不可以相互调用,但可以将所有公共构造部分放在一个成员函数init中,所有的构造函数调用这个构造函数。

下面这段代码来自《Core Java》一书,描述了不同的类的初始化方式:

 1 /**
 2    @version 1.00 2000-01-27
 3    @author Cay Horstmann
 4 */
 5 
 6 import java.util.*;
 7 
 8 public class ConstructorTest
 9 {
    public static void main(String[] args)
    {
       // fill the staff array with three Employee objects
       Employee[] staff = new Employee[3];
 
       staff[0] = new Employee("Harry", 40000);
       staff[1] = new Employee(60000);
       staff[2] = new Employee();
 
       // print out information about all Employee objects
       for (int i = 0; i < staff.length; i++)
       {
          Employee e = staff[i];
          System.out.println("name=" + e.getName()
             + ",id=" + e.getId()
             + ",salary=" + e.getSalary());
       }
    }
 }
 
 class Employee
 {
    // three overloaded constructors
    public Employee(String n, double s)
    {
       name = n;
       salary = s;
    }
 
    public Employee(double s)
    {
       // calls the Employee(String, double) constructor
       this("Employee #" + nextId, s);
    }
 
    // the default constructor
    public Employee()
    {
       // name initialized to ""--see below
       // salary not explicitly set--initialized to 0
       // id initialized in initialization block
    }
 
    public String getName()
    {
       return name;
    }
 
    public double getSalary()
    {
       return salary;
    }
 
    public int getId()
    {
       return id;
    }
 
    private int id;
    private static int nextId;
 
    // object initialization block
    {
       id = nextId;
       nextId++;
    }
 
    // static initialization block
    static
    {
       Random generator = new Random();
       // set nextId to a random number between 0 and 9999
       nextId = generator.nextInt(10000);
    }
 
    private String name = ""; // instance variable initialization
    private double salary;
 }

5. Java 和 C++ 析构过程的差异

不要因为Java的垃圾回收机制而忽视了资源的手动回收!

Java有自带的垃圾回收机制,手动的内内存回收是不必要的,所以Java没有显示的支持构造函数。但是有时有些对象中的资源并不一定是内存资源,而有可能是

一个文件或者其他系统资源的句柄!在这些情况下,当这些资源不再被使用的时候,对其的释放就显得很重要了。

Java 中可以为每个类提供一个finalize函数,当垃圾回收器清除对象之前,finalize函数会被调用。但实际中不能依赖这个finalize函数来实现资源的回收,因为

finalize函数会出现一些未定义的行为。建议定义一个手工的方法来释放支援,而不是完全依赖Java语言的垃圾回收机制。例如,可以在类的定义中定义一个叫

close的方法,当使用完对象之后,调用close方法以释放占用的资源.

     

Java面向对象程序设计--与C++对比说明:系列1(面向对象基础)的更多相关文章

  1. Java面向对象程序设计--与C++对比说明:系列3(Java 继承机制)

    继承(inheritance)背后的核心思想是:       bonus = b;    }      } Java没有像C++那样提供多继承机制,但提供了接口机制,在后面我们将详细探究接口机制的实现 ...

  2. Java面向对象程序设计--与C++对比说明:系列2(类机制)

    1. Java中的包机制(Package): 1.1   Java容许将一系列的类组合到一个叫package的集合中.package机制是一种非常好的管理工作的方式并可以将你自己的工作和系统或第三方提 ...

  3. 【 .NET 面向对象程序设计进阶》】【 《.NET 面向对象编程基础》】【《正则表达式助手》】

    <.NET 面向对象程序设计进阶> <.NET 面向对象程序设计进阶> <正则表达式助手>

  4. 2018-2019-20175203 实验二 《Java面向对象程序设计》

    2018-2019-20175203 实验二 <Java面向对象程序设计>实验报告 实验要求 没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑 ...

  5. [.net 面向对象程序设计深入](0) 开篇

    [.net 面向对象程序设计深入](0)开篇        [.net 面向对象编程基础]和 [.net 面向对象程序设计进阶]在15年底写完了,群里也加进来不少热爱学习的小伙伴.让我深切感受到在这个 ...

  6. 《MATLAB面向对象程序设计》

    <MATLAB面向对象程序设计> 基本信息 作者: 苗志宏    马金强 出版社:电子工业出版社 ISBN:9787121233449 上架时间:2014-6-18 出版日期:2014 年 ...

  7. OOP_面向对象程序设计概述

    李际军老师"面向对象程序设计"课程第一课笔记整理 面向对象程序设计概述 20世纪90年代以来面向对象程序设计(Object Oriented Programming, 简称OOP) ...

  8. 201871010128-杨丽霞《面向对象程序设计(Java)》第十二周学习总结

    201871010128-杨丽霞<面向对象程序设计(Java)>第十一周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ ...

  9. 实验二 Java面向对象程序设计

    实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...

随机推荐

  1. Unity给力插件之MeshBaker

    这是一个用来合并网格.材质.贴图的插件. 其实网上也有一些比较详细的使用说明,但是真实操作起来时,总是有一些搞不清bug.而且,作为功能比较全的插件,在Unity版本更新时,也难免会一些不兼容的地方. ...

  2. ASP.NET 路由

    URL 模式可以包含文本值和变量占位符(也称为“URL 参数”).  文本和占位符位于由斜杠 (/) 字符分隔的 URL 段中. 当生成请求时,URL 分析为段和占位符,变量值提供给请求处理程序.  ...

  3. Keepass 2.x 的一些新发现

    近期将 Keepass 从 1.22 升级到了 2.24,经过一番折腾,发现有了很多新功能,也有一些之前被忽视的地方.再一次感叹这个软件的强大,向作者的无私奉献致敬! 其实,这个软件一直有 1.x 和 ...

  4. Windows不能在本地计算机启动OracleDBConsoleorcl .错误代码2

    Windows 不能在 本地计算机 启动 OracleDBConsoleorcl.有关更多信息,查阅系统事件日志.如果这是非 Microsoft 服务,请与服务厂商联系,并参考特定服务错误代码 2. ...

  5. admin-openrc

    #!/bin/bash # To use an Openstack cloud you need to authenticate against keystone, which # returns a ...

  6. 安装Office时出现windows installer服务不能更新一个或多个受保护的windows文件错误的解决方法

    今天在Windows XP上安装Microsoft Office 2010时,总是遇到“Windows Installer服务不能更新一个或多个受保护的windows文件,安装失败,正在回滚更改”提示 ...

  7. Git 版本控制工具(学习笔记)

    GIT(分布式) 一.Git 初始版本控制工具 1. 安装Git Ubuntu系统下,打开shell界面,输入: sudo apt-get install git-core  之后回车输入密码,即可完 ...

  8. WPF ArrangeOverride与MeasureOverride

    1.MeasureOverride  是FrameworkElement.MeasureOverride 方法 当重写在派生类中,单位是对于子元素所需要布局的大小并确定FrameworkElement ...

  9. Scene的实时追踪显示

    最近在处理酷跑类型游戏时,遇到一个功能需求:需要在摄像机实时追踪角色显示(Game)的同时,Scene同时实时显示NPC的位置状态等信息? 这个问题有三种解决方法,各有利弊:1)使用unity系统内置 ...

  10. 【转】Android 混淆代码总结

    http://blog.csdn.net/lovexjyong/article/details/24652085 为了防止自己的劳动成果被别人窃取,混淆代码能有效防止被反编译,下面来总结以下混淆代码的 ...