C ++内存分配 - 将子类分配给类

时间:2012-12-07 17:50:11

标签: c++ pointers memory-management

编辑:没有代码是我的,它全部都给了我,我只是从对象分配方法的角度来分析它。

我的内存分配非常困难。我向你保证,在过去的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();
} 

2 个答案:

答案 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的部分。