为啥这会给我一个 Java 中的 ClassCastException,而它在 C++ 中运行良好?

Posted

技术标签:

【中文标题】为啥这会给我一个 Java 中的 ClassCastException,而它在 C++ 中运行良好?【英文标题】: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 【参考方案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:我不会投反对票,因为我没有很多声誉。但我很感谢你的回答!

以上是关于为啥这会给我一个 Java 中的 ClassCastException,而它在 C++ 中运行良好?的主要内容,如果未能解决你的问题,请参考以下文章

为什么这会给我一个java中的算术错误?

为啥 TypeScript 中的 'instanceof' 会给我错误“'Foo' 仅指一种类型,但在这里被用作值。”?

为啥从 URL 末尾删除 / 会给我一个 403?

为啥这个 fgets 函数会给我一个分段错误?

为啥 pHp 会给我这个错误? [复制]

为啥苹果推送通知服务有时会给我错误 500?