C++和Java中关于继承的点点滴滴

本文通过一个Java示例探讨了多态性的工作原理及其在编译过程中的表现,解释了子类对象赋值给父类引用时的行为特征,并通过Java字节码指令解析了运行时类型确定的方法调用。

 

1. Java篇

import java.util.ArrayList;

import java.util.Stack;

 

    class Super

    {

        static String greeting() { return "Goodnight"; }

        String name() { return "Richard"; }

    }

    class Sub extends Super

    {

        static String greeting() { return "Hello"; }

        String name() { return "Dick"; }

        String name2() { return "Dick2"; }

    }

    public class Test3

    {

        public static void main(String[] args)

        {

            Super s = new Sub();

            //s.name2();

            System.out.println(s.greeting() + ", " + s.name());

        }

    }

 

 

Test3会输出什么呢? s在Java VM空间是Super还是Sub? s.name2会不会有编译错误?

 

执行D:/workspace/2009Java/test/bin>D:/Java/jdk/bin/javap -c Test3 >Test3.bytecode, 来看看java的opcode.

 

Compiled from "Test3.java"

public class Test3 extends java.lang.Object{

public Test3();

  Code:

   0: aload_0

   1: invokespecial #8; //Method java/lang/Object."<init>":()V

   4: return

 

public static void main(java.lang.String[]);

  Code:

   0: new #16; //class Sub

   3: dup

   4: invokespecial #18; //Method Sub."<init>":()V

   7: astore_1

   8: getstatic #19; //Field java/lang/System.out:Ljava/io/PrintStream;

   11: new #25; //class StringBuilder

   14: dup

   15: invokestatic #27; //Method Super.greeting:()Ljava/lang/String;

   18: invokestatic #33; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;

   21: invokespecial #39; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V

   24: ldc #42; //String , 

   26: invokevirtual #44; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

   29: aload_1

   30: invokevirtual #48; //Method Super.name:()Ljava/lang/String;

   33: invokevirtual #44; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

   36: invokevirtual #51; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;

   39: invokevirtual #54; //Method java/io/PrintStream.println:(Ljava/lang/String;)V

   42: return

 

}

 

invokevirtualInvoke instance method, dispatch based on run-time type
 
invokestatic

Invoke a class (static) method

 

 

2. Run-time type is Sub, Class type is Super. 所以会有以上的输出. 至于s.name2的错误,编译器检查的结果.

 

2. C++篇

 

 

import java.util.ArrayList;

import java.util.Stack;

 

    class Super

    {

        static String greeting() { return "Goodnight"; }

        String name() { return "Richard"; }

    }

    class Sub extends Super

    {

        static String greeting() { return "Hello"; }

        String name() { return "Dick"; }

        String name2() { return "Dick2"; }

    }

    public class Test3

    {

        public static void main(String[] args)

        {

            Super s = new Sub();

            //s.name2();

            System.out.println(s.greeting() + ", " + s.name());

        }

    }

 

 

这样的输出又是什么呢?

 

 

Coming from a C# background you never need to worry about issues like as you always pass objects by reference and there is no such thing as copy constructors, assignment operator overloads and the obvious one is that all objects are on the heap meaning that assigning a to b means b and a point to the same thing.

In c++ you have the choice to create an object on the free store or create it on the stack. When objects are store on the stack and a is assigned to b then the copy constructor or the asignment overload will run and copy the object to the other object doing a memberwise / shallow copy.

This becomes a problem when you have a function that takes a base class object without reference semantics. You think that it supports polymorphism but it does not. when you invoke the virtual method it always calls the super classes methods. Why? This is because it was copied to a super class object and all reference to the sub class was lost.

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值