编辑:没有代码是我的,它全部都给了我,我只是从对象分配方法的角度来分析它。
我的内存分配非常困难。我向你保证,在过去的5个小时里我已经看了一百个例子。我知道这可能措辞不好而且我提前道歉。
1。)我不明白为什么版本2会打印A类的f()而不是B类。这条线
A* objA1 = objB;
声明一个指向objA1的指针,该指针指向A类型的对象,并将其地址分配给objB指向的位置,B(2,3)。我读过句子“如果它们是堆动态对象,那么你可以将b1分配给a1”。当我打电话给objA1-> f()时,我只是说去这个地方,哦,你找到了B?把它投入A并调用f()。
2。)我原本认为版本1切掉了objB,因为它说这个对象已经为A分配了空间,等于B更大。但如果我把cout<< objB.bf;在此作业之后,它仍然有效。是一个objA1 = objB;不是静态地声明objA1?再一次,为什么不打印B的f()?
3。)两个objA1任务有什么区别?因为什么功能只适用于两者中的一个。如果你想给它一个过时的分类分类,你能称之为“堆动态”吗?
class A {
private:
int a;
public:
A(int ia) {a = ia;}
void f() {
cout << "Call to method f defined in class A" << endl;
}
};
class B : public A {
private:
int b;
public:
B(int ia, int ib) : A(ia) {b = ib;}
void f() {
cout << "Call to method f specialized in class B" << endl;
}
void bf() {
cout << "Call to class B own method bf" << endl;
}
};
// C++ driver - Version 1
void main() {
A objA = A(1);
B objB = B(2,3);
objA.f();
objB.f();
objB.bf();
A objA1 = objB;
objA1.f();
}
// C++ driver - Version 2
void main() {
A* objA = new A(1);
B* objB = new B(2,3);
objA->f();
objB->f();
objB->bf();
A* objA1 = objB;
objA1->f();
}
答案 0 :(得分:2)
您需要在基类中将您希望以多态方式(通过指向base的指针)的函数声明为virtual
。当编译器通过对象的指针(或引用)遇到对virtual
函数的调用时,它会查找该对象的动态类型的函数,而不是静态类型。因此,只需将virtual
贴在A
:
virtual void f() {
cout << "Call to method f defined in class A" << endl;
}
您的行A objA1 = objB;
确实会对您的B
对象进行切片,只会将其A
部分复制到objA1
。您只能在A
上拨打objA1
的成员函数。但是,objB
仍然是它始终存在的同一个对象 - 它仍然是B
,并且所有B
的成员函数都可用。您可以愉快地致电objB->bf()
,但不能致电objA->bf()
或objA1->bf()
。
如果有疑问,只需查看您正在调用函数的对象的类型。如果是A
,您只能调用A
的函数,同样使用B
。如果您通过指针访问并调用virtual
函数,则调用属于该对象的dynamic type
的函数(而不是指针所说的它的类型)指着)。
答案 1 :(得分:1)
默认情况下,C ++不使用动态分派。这意味着在p->f()
被声明为p
时调用X *p
将始终调用X::f()
,无论指向的实例的动态类型如何p
。要启用动态分派,必须将该函数声明为virtual
。这与Java / C#形成对比,其中所有成员函数都隐式virtual
。
确实会出现“版本1”中的切片,但objB
决不会因为被分配到某处而受到影响。切片会影响objA
(即它会忽略objB
不属于A
的部分。