为什么继承在Java和C++;超类调用(或不调用)子类';方法? 我已经写了——在爪哇和C++中,似乎是完全相同的继承例子。看到这些程序的不同输出,我真的很惊讶。让我分享代码片段和相应的输出
C++代码:为什么继承在Java和C++;超类调用(或不调用)子类';方法? 我已经写了——在爪哇和C++中,似乎是完全相同的继承例子。看到这些程序的不同输出,我真的很惊讶。让我分享代码片段和相应的输出,java,c++,inheritance,Java,C++,Inheritance,C++代码: class A { public: A() {} void sleep() { cout << "A.Sleep" << endl; eat(); } void eat() {cout << "A.Eat" << endl;} }; class B: public A { public: B() {} void s
class A
{
public:
A() {}
void sleep() {
cout << "A.Sleep" << endl;
eat();
}
void eat() {cout << "A.Eat" << endl;}
};
class B: public A
{
public:
B() {}
void sleep() {
A::sleep();
cout << "B.Sleep " <<endl;
this->eat();
}
void eat() {
cout << "B.Eat" << endl;
run();
}
void run() {
A::sleep();
cout << "B.run" << endl;
}
};
int main()
{
B *b = new B();
b->sleep();
}
A.Sleep
A.Eat
B.Sleep
B.Eat
A.Sleep
A.Eat
B.run
executed successfully...
class A
{
A() {}
void sleep() {
System.out.println("A.Sleep");
this.eat();
}
void eat() { System.out.println("A.Eat");}
};
class B extends A
{
B() {}
@Override
void sleep() {
super.sleep();
System.out.println("B.Sleep");
this.eat();
}
@Override
void eat() {
System.out.println("B.Eat");
run();
}
void run() {
super.sleep();
System.out.println("B.Run");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.sleep();
}
}
A.Sleep
B.Eat
A.Sleep
B.Eat
A.Sleep
......
......
......
(Exception in thread "main" java.lang.StackOverflowError)
Java代码:
class A
{
public:
A() {}
void sleep() {
cout << "A.Sleep" << endl;
eat();
}
void eat() {cout << "A.Eat" << endl;}
};
class B: public A
{
public:
B() {}
void sleep() {
A::sleep();
cout << "B.Sleep " <<endl;
this->eat();
}
void eat() {
cout << "B.Eat" << endl;
run();
}
void run() {
A::sleep();
cout << "B.run" << endl;
}
};
int main()
{
B *b = new B();
b->sleep();
}
A.Sleep
A.Eat
B.Sleep
B.Eat
A.Sleep
A.Eat
B.run
executed successfully...
class A
{
A() {}
void sleep() {
System.out.println("A.Sleep");
this.eat();
}
void eat() { System.out.println("A.Eat");}
};
class B extends A
{
B() {}
@Override
void sleep() {
super.sleep();
System.out.println("B.Sleep");
this.eat();
}
@Override
void eat() {
System.out.println("B.Eat");
run();
}
void run() {
super.sleep();
System.out.println("B.Run");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.sleep();
}
}
A.Sleep
B.Eat
A.Sleep
B.Eat
A.Sleep
......
......
......
(Exception in thread "main" java.lang.StackOverflowError)
输出:
class A
{
public:
A() {}
void sleep() {
cout << "A.Sleep" << endl;
eat();
}
void eat() {cout << "A.Eat" << endl;}
};
class B: public A
{
public:
B() {}
void sleep() {
A::sleep();
cout << "B.Sleep " <<endl;
this->eat();
}
void eat() {
cout << "B.Eat" << endl;
run();
}
void run() {
A::sleep();
cout << "B.run" << endl;
}
};
int main()
{
B *b = new B();
b->sleep();
}
A.Sleep
A.Eat
B.Sleep
B.Eat
A.Sleep
A.Eat
B.run
executed successfully...
class A
{
A() {}
void sleep() {
System.out.println("A.Sleep");
this.eat();
}
void eat() { System.out.println("A.Eat");}
};
class B extends A
{
B() {}
@Override
void sleep() {
super.sleep();
System.out.println("B.Sleep");
this.eat();
}
@Override
void eat() {
System.out.println("B.Eat");
run();
}
void run() {
super.sleep();
System.out.println("B.Run");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.sleep();
}
}
A.Sleep
B.Eat
A.Sleep
B.Eat
A.Sleep
......
......
......
(Exception in thread "main" java.lang.StackOverflowError)
我不知道为什么这两个继承的例子表现不同。难道它不应该同样起作用吗
<>强>对这个场景的解释是什么?< /强> 在C++实例中,你是基本方法,但是你不重写它们。所以它们实际上是不同的方法,只是碰巧有相同的名称。如果你打电话
A* a = new B();
a->sleep();
它实际上会打印“A.Sleep”
。如果要重写方法,则需要在基类中声明它(在所有子类中也会自动使其成为虚拟的)。您可以阅读更多关于函数隐藏与VC++中的重写。
在Java示例中,您实际上重写了这些方法,因此它们是相同的方法。一个代替旧的。您可以这样想:所有Java函数都被秘密标记为
virtual
,这意味着它们可以被重写。如果希望方法在Java中不可重写,则必须声明它。注意:要小心,每种语言都有自己的思维方式。有很多方法可以解释/实现OO。即使C++和java看起来相似,它们也不太相似。
在这两种语言中,编译器在编译时通过检查类(以及从当前类继承的类等)是否具有正确的签名和可见性,验证是否可以调用方法。使事情不同的是呼叫真正发出的方式
C++:
在非虚拟方法的情况下调用的方法在编译时完全确定。这就是为什么即使对象是类B
,当它执行A::sleep
时,对eat
的调用被解析为对A::eat
的调用(eat
不是虚拟的,那么编译器调用A::eat
,因为您处于A
级别)。在B::sleep()
中,对this->eat()
的调用被解析为对B.eat()
的调用,因为在那里this
属于B
类型。您不能进入继承层次结构(在类A
中调用eat
将永远不会在下面的类中调用eat
方法)
请注意,在虚拟方法的情况下情况是不同的(它与Java情况更相似,但不同)
Java:
在Java中,调用的方法在运行时确定,并且是与对象实例最相关的方法。因此,在A.sleep
中,对eat
的调用将是与当前对象类型相关的调用,这意味着类型B
(因为当前对象属于类型B
),然后将调用B.eat
然后会出现堆栈溢出,因为在处理类型为
B
的对象时,调用B.sleep()
将调用a.sleep()
,后者将调用B.eat()
,后者将调用B.run()
,后者将调用a.sleep()
,在Java中,所有方法都是虚拟的(即受重写约束)。在C++中,它们不是。如果给基类中的一个与非虚方法同名的子类,它们只是两个类似命名的方法。我将把标题/问题改成“在这种情况下C++和java继承有什么区别?”,因为为什么?仅仅因为C++和java是两种不同的语言,为什么它不一样呢?在两种不相关的语言之间进行并行通常会适得其反,因为Java中的方法是默认的。“我用Java和C++编写了完全相同的继承示例”-没有。您试图尽可能接近相同的语法(并且没有用重写关键字来实现)。“Cest+'在C++中确实有相同的含义,BTW. @ MalStruts Trtrue,但这仅在基类已经将该方法定义为虚拟时才是必要的。