最近学习了C++ 觉得同为面向对象,Java 和C++ 中的一些地方实是让我想写一下,写着写着写着,不免觉得语言真是一个可爱的东西(或许他不是个东西)
一:C++中的对象的声明,就类似于C语言中的类型和变量的关系:
Point p() ;
p 是引用,创建的实例的名字就是p 相当于 int a;。所以在C++ 中还有指针。
二:Java 中的对象就是创建
Date today=new Date();
new Date();构造了一个Date的对象,它的值是对对新创建的引用,而这个引用储存在变量中(today);
Date today; 就相当于声明了一个Date 类型的容器(可以这样理解,有点类似于指针)。单独这样声明的today 是什么也干不了的。它里面存储的应该是new Date(); 这个对象的引用,容器中存储了引用,才能使用。这里的引用只能是三种类型(1.类本身的实例2.子类的实例3.实现类的实例)。
注意在Java中两个十分重要的概念:
对象和对象的引用的概念:参照:https://www.cnblogs.com/gaoxiangde/p/4379862.html
Point p; 是Point类型的引用。
new Point(); 是一个类的实例(对象,对象是没有名字的)
p=new Point() ; p 是 new Point() 这个对象的引用
指针和引用:
**都是地址的概念;**
指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元,即指针是一个实体;
而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已
在C++ 中有指针也有引用,在Java中只有引用
(C++ 中指针和引用的区别:https://blog.youkuaiyun.com/qq_27678917/article/details/70224813)
java 和C++ 的对象的创建概念上的区别最明显的就是体现在对象作为参数传递的时候。Java 相当于在对堆中创建的new P() 这个对象,C++ 中对象做参数转递相当于int a 传递。函数中对这个对象的操作丝毫不影响,这个对象本身
C++ 和Java 中的静态绑定和动态绑定:
- 程序绑定的概念:
绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定 - 静态绑定(早绑定 编译器绑定):
在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C 。针对java可以理解为程序编译期的绑定 - 动态绑定(迟绑定 运行期绑定):
后期绑定:在运行时根据具体对象的类型进行绑定。
若一种语言实现了后期绑定,同时必须提供一些机制在运行期间判断对象的类型,并分别调用适当的方法。也就是说编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。可以这样认为:它们都要在对象中安插某些特殊类型的信息。
动态绑定的过程:
1.虚拟机提取对象的实际类型的方法表
2.虚拟机搜索方法签名
3.调用方法
关于绑定相关的总结:
了解三者的概念之后,我们发现java属于后期绑定。在java中,几乎所有的方法都是后期绑定,在运行时动态绑定方法属于子类还是基类。但也有特殊,针对s**tatic方法和final方法由于不能被继承,因此在编译时就可以确定他们的值,他们是属于前期绑定。特别说明的一点,private声明的方法和成员变量不能被子类继承,**所有的private方法都被隐式的指定为final的(由此我们知道:将方法声明为final类型的 一是为了防止方法被覆盖,二是为了有效的关闭java中的动态绑定)。java中的后期绑定是由JVM来实现的,我们不用去显式的声明它, 而C++则不同,必须明确的声明某个方法具备后期绑定。 java当中的向上转型或者说多态是借助于动态绑定实现的,所以理解动态绑定,也就搞定向上转型和多态。
对于java当中的方法而言,除了final,static,private和构造方法是前期绑定外,其他的方法全部为动态绑定。而动态绑定的典型发生在父类和子类的转换声明之下:
比如:Parent p = new Children();
具体过程如下:
1:编译器检查对象的声明类型和方法名。假设我们调用x.f(args)方法,并且x已经被声明为C类的对象,那么编译器会列举出C类中所有的名称为f的方法和从C类的超类继承过来的f方法
2:接下来编译器检查方法调用中提供的参数类型。如果在所有名称为f 的方法中有一个参数类型和调用提供的参数类型最为匹配,那么就调用这个方法,这个过程叫做“重载解析”
3:当程序运行并且使用动态绑定调用方法时,虚拟机必须调用同x所指向的对象的实际类型相匹配的方法版本。假设实际类型为D(C的子类),如果D类定义了f(String)那么该方法被调用,否则就在D的超类中搜寻方法f(String),依次类推
C++ 中除了声明为Vitual 的函数其他的都是静态绑定。
C++ 和Java中的静态绑定和动态绑定遵循的规则都是一样的,只是具体的体现方式不一样:
总结:
静态绑定: 根据引用的类型决定,明确这个方法由那个类调用(那个类的对象调用)而且是在编译时就已经绑定了。
这里说的对象的引用的类型是指:
★★★对象的引用类型还规定了对象可以调用那些函数(在C++和Java中都是一样的)
例如:类A继承B 两个类中都有方法x,y。 子类A中有自己的特有方法z
b=a; 对象的引用b 此时的值是new A() 这个对象。
根据动态绑定b.x() 执行的是A 中的x.
但是b.z() 是错误的。因为引用变量b 的类型是B 他能调用的方法只有xy。
动态绑定:根据对象的类型来决定
Java:编译时完成静态绑定,运行时完成动态绑定(运行时才创建对象)
C++:编译时完成静态绑定,只有声明为Virtual 的方法,才在运行时根据对象的类型调用。并且是:通过成员函数,指针,引用来访问Virtual 虚函数,才能实现动态绑定,如果是通过对象名来访问就是动态绑定。
例如:★★★
类A 继承类B,并且在两个类中声明了一样的函数 display(){...}
在主函数中有这样的使用
C++:
A a();
B b();
a=b;
cout<<a,display();
//执行的是A 中的display() 这是静态绑定。在编译时,A中的display 就绑定了类A,B 中的就绑定了B类
Java :
A a = new A();
B b = new B();
a=b;
System.out.print(a.display());
//执行的是 B 中的display () 这是动态绑定,在运行时,a这个引用变量存储的对象是: new B()
所以执行的是B 中的display()
C++ 中的动态绑定:
主函数中的测试代码:
B &b1,*b2,b3();
A a();
b1=a;
b1.display();//执行的是A 中的display() b1 这个引用变量中存储的是a 这个对象的引用
b2=&a;
b2.display() : //执行的是A 中的display() b2 这个指针指向的对象的类型是A
b3=a;
b3.display();//执行的是B 这个类中的display() 这个是静态绑定
动态绑定和静态绑定体现了Java 和C++ 中的多态
在Java 中:
b=a; 是多态的体现
在C++ 中:
b=a : 只是赋值兼容性的体现
在Java 和C++ 中子类/派生类调用子类父类(基类派生类)的同方法(名字和参数表一样)先在下级找,找不到再去上级。
C++ 和Java 的继承大部分是相似的,要特别注意的就是关于动态绑定和静态绑定。