【问题标题】:Why would this give me a ClassCastException in Java, while it works well in C++?为什么这会给我一个 Java 中的 ClassCastException,而它在 C++ 中运行良好?
【发布时间】:2017-06-05 04:01:47
【问题描述】:

有些事情让我发疯了。

假设我们有这些简单的类

public class Animal {
public void makeSound() {
    System.out.println("From Animal");
  }
}

public class Dog extends Animal {
public void makeSound() {
    System.out.println("From Dog");
}

public void flip() {
    System.out.println("Flipped");
}

public static void main(String[] args) {
  Animal a= new Animal();
  ((Dog)a).makeSound(); // Gives me an error at runtime.    

}

C++ 代码:

class Animal {
   public: 
          virtual void makeSound(){ cout<<" From Animal";}
};

class Dog : public Animal {
    public : void makeSound(){ cout<<" From Dog ";}
             void  flip() { cout<<"Flipped";}
};

 main() {
Animal *a = new Animal();
((Dog*)a)->makeSound(); // returns From animal 

  }

为什么它会在 Java 中产生运行时错误,而在 C++ 中却没有问题?

谢谢

【问题讨论】:

  • 它确实“工作没有问题”。由于 C 遗留问题,这是未定义的行为。
  • 狗是动物,但动物不一定是狗
  • 可能与同一示例重复 explicit casting from super class to subclass
  • 也许有些人会使用相同的示例,因为它在 Java 或 C++ 教程网站上随处可见,但只是在 Java 和 C++ 中使用相同的示例,我发现在 Java 中出现错误,而C++ 中没有错误,它执行没有问题
  • @ZikoUdeM 这不是 C++ 的错。 C 风格的转换只是不做任何运行时类型检查。如果需要,请使用 dynamic_cast

标签: java c++ inheritance casting runtime-error


【解决方案1】:

您的示例无法正常工作;它的行为是不确定的。

C++ 有几种不同类型的强制转换操作。您在这里使用的是C-style cast(从技术上讲,它最终会执行static_cast)。 C 风格的转换不做任何运行时类型检查。由程序员来确保所涉及的类型有意义。如果您想要运行时类型检查,请使用dynamic_cast。将dynamic_cast 与指针一起使用时,如果对象实际上不是要转换为的类型的实例,则转换将失败并返回nullptr。使用引用时会抛出std::bad_cast

class Animal {
public: 
    virtual void makeSound() { std::cout << "From Animal\n"; }
};

class Dog : public Animal {
public:
    void makeSound() { std::cout << "From Dog\n"; }
};

int main() {
    Animal *a = new Animal();
    Dog* d = dynamic_cast<Dog*>(a);
    if (d == nullptr) {
        std::cout << "cast failed\n";
    } else {
        d->makeSound();
    }
}

Live example

【讨论】:

    【解决方案2】:

    只有在代码中的某个位置引用子类时(例如,在 Java 中)才可能进行向下转换

    Animal a = new Dog(); 
    ((Dog)a).makeSound();
    

    【讨论】:

    • 对否决票的任何解释将不胜感激。谢谢。
    • 通常这是有效的,因为我们现在 a 是一只狗,但只有 Animal 的方法。在这里进行向下转换时,我们也可以访问 Dog 的方法。因此,在这两种情况下,如果在向下转换之前和之后直接调用 makeSound() 将始终返回 From Dog。 P.S:我不会投反对票,因为我没有很多声誉。但我很感谢你的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多