当我来到c ++时,我是一个新手,当我研究虚拟函数和纯虚函数时,我发现它与以不同方式实例化对象的方式不同。这让我很困惑。如果你能提供帮助,我将不胜感激。以下是代码和输出。
#include <iostream>
using namespace std;
class A {
public:
int va;
int vb;
virtual void m1() {
cout << "this is A's m1() method" << endl;
}
void m3() {
cout << "this is A's m3() method" << endl;
}
};
class B : public A {
public:
void m1() {
cout << "this is B's m1() method" << endl;
}
void m2() {
cout << "this is B's m2() method" << endl;
}
void m3() {
cout << "this is B's m3() method" << endl;
}
};
int main() {
cout << "start" << endl;
A a1 = B();
a1.m1();
a1.m3();
cout << "===================" << endl;
A *a2;
a2 = new B();
a2->m1();
a2->m3();
delete[]a2;
/*
output:
this is A's m1() method
this is A's m3() method
===================
this is B's m1() method
this is A's m3() method
*/
return 0;
}
我想知道A a1 = B();
和A *a2; a2 = new B();
之间的区别。感谢您的帮助。
答案 0 :(得分:0)
我想知道A a1 = B();
和A *a2; a2 = new B();
之间的区别。
A a1 = B();
会将B临时切片到A堆栈变量。 B的任何其他成员变量或行为都将被丢弃。 A堆栈变量a1
将在范围的末尾被破坏。
A *a2; a2 = new B();
将有一个指针指向全局存储分配的B对象。 a2
变量将指向该B对象,该对象仍然是B对象。在B中重写的A的虚拟方法将使用B方法。 A的非虚方法可通过A指针访问,但除非使用强制转换,否则无法访问B(虚拟或非虚拟)的其他方法。
delete[]a2;
是未定义的行为,在我的机器上会使应用程序崩溃。由于B对象是使用new B()
在全局商店中分配的,因此应使用delete a2;
删除它。
答案 1 :(得分:0)
你碰巧知道/学习Java吗?在C ++中,事情有点不同。
A a1
是A
类型的对象,无论您如何构造它。特别是:
A a1 = B();
以下内容:
B
a1
的对象A
。它会将临时内容复制到a1
。只会复制临时的A
部分。B
对象被销毁。这就是为什么a1
上的所有方法都是真正的A
方法。没有虚拟机制会达到B的方法,因为a1
不是B
类型的对象。
A* a2
是指向A
或派生类型的任何对象的指针。它只是一个指针,它本身并不代表一个对象。
现在,当您为其指定new B()
时,它将指向实际类型B
的对象。通过这个指针调用虚方法将达到B
的方法,就像你预期的那样。
顺便说一句。通过指针引用的单个对象应通过delete a2
删除。如果您有数组,则使用delete [] a2
。