2012-12-07 90 views
0

编辑:没有任何代码是我的,它全部都给了我,我只是从对象分配方法的角度分析它。C++内存分配 - 分配子类到

我在内存分配方面非常辛苦。我向你保证,在过去的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

'main'返回'int',而不是'void'。 – GManNickG

回答

1

默认情况下,C++不使用动态分派。这意味着,当p宣布为X *p时,将调用p->f()总是调用X::f(),而不管p指向的实例的动态类型如何。要启用动态调度,该功能必须声明为virtual。这与Java/C#形成鲜明对比,其中所有成员函数都隐式地为virtual

确实发生了“版本1”中的切片,但是,objB不受任何方式的影响。它是objA受切片影响(即它忽略objB的不属于A的部分)。

+0

你能帮我了解两个objA1任务之间的区别吗?因为哪些功能只适用于两者之一。如果你想给它一个过时的分类分类,你可以称它们为“堆 - 动态”吗? –

+0

@ caleb.breckon'A objA1 = objB;'(其中'objB'类型为'B')在堆栈上创建类型为'A'的对象'objA1'(变量的值就是对象本身)。 'a * objA1 = objB;'(其中'objB'是类型'B *')** **指针** - 赋值后,objA1和objB都指向相同'objB'的实例,它使用'new'在堆上分配。 – Angew

2

你需要声明的是,你希望被称为多态(通过指针基地)作为基类virtual的功能。当编译器通过指向对象的指针(或引用)遇到对函数virtual的调用时,它将查找该对象的动态类型的函数,而不是静态类型。因此,简单地把virtual在函数定义的前面A

virtual void f() { 
    cout << "Call to method f defined in class A" << endl; 
} 

你行A objA1 = objB;确实切片您B对象,只是在复制它的A部分objA1。您只能在objA1上拨打A的会员功能。但是,objB仍然是它始终存在的相同对象 - 它仍然是B,并且具有B的所有可用成员函数。您可以愉快地拨打objB->bf(),但不是objA->bf()也不是objA1->bf()

如果有疑问,只要看看你打电话给你的功能对象的类型。如果是A,则只能拨打A的功能,并且也可以拨打B。如果您通过指针访问并调用函数,则调用属于对象dynamic type的函数(而不是指向它指向的指针的类型)。

+0

你能帮我了解两个objA1任务之间的区别吗?因为哪些功能只适用于两者之一。如果你想给它一个过时的分类分类,你可以称它们为“堆 - 动态”吗? –

+0

@ caleb.breckon第一种方法是给'A *'分配一个'B *'指针 - 这非常好,并且不会发生对象切片,因为您不复制它们指向的对象。然而,当你将一个“B”类型的对象赋给一个类型为“A”的对象时,你实际上是在将一个对象的值拷贝到另一个对象上,而显然“B”的值不能适合值一个'A',所以你得到物体切片。 –