当我们使用基指针创建它时调用派生类的构造函数

时间:2012-06-21 23:39:09

标签: c++ inheritance constructor destructor

Class Shape {
    virtual Shape() = 0;
    virtual ~Shape() = 0;
}

Class Circle : Public Shape {
    Circle();
    ~Circle();
    // Something ...
}

int main () {
Shape* s = new Circle();
delete s;
}

它是否正在调用Circle的构造函数?即使它与Shape的构造有不同的名称? 当你删除s时,你是在调用Circle的析构函数吗?

3 个答案:

答案 0 :(得分:1)

在c ++中,构造函数不能是虚拟的。

您提供的代码无效c ++。

以下是更正后的代码,您可以在此处查看:http://codepad.org/2fDc4S3e 程序的输出应该回答你的所有问题。我建议您使用代码来回答您可能遇到的任何其他问题。

class Shape {
public:
    virtual ~Shape() = 0;
};

Shape::~Shape() { std::cout << "Shape dtor called" << std::endl;} // Since you declared the destructor pure virtual you must define it

class Circle : public Shape {
public:
    Circle() { std::cout << "Circle ctor called." << std::endl; }
    ~Circle() { std::cout << "Circle dtor called." << std::endl; }
    // Something ...
};

int main () 
{
  Shape* s = new Circle(); // This will call the constructor of Circle
  delete s; // This will call the destructor of Circle and then the dtor Shape.
  return 0;
}

答案 1 :(得分:0)

是的,Circle的dtor将被称为:

  • 因为Shape的dtor是虚拟的,所以从它继承的任何类都会有一个虚拟的dtor。
  • 这意味着不直接调用dtor,而是通过v-table调用:当你“删除s”时,调用s.dtor()调用v-table中的正确项目,即Circle的dtor。

答案 2 :(得分:0)

构造函数不能是虚拟的。

class Shape {
    virtual ~Shape() = 0;
};

class Circle : public Shape {
    Circle() {};
    ~Circle() {};
};

int main() {
    Shape *s = new Circle();
    delete s;
}

是的,new Circle()调用Circle的构造函数。这是因为表达式new <type><optional initializer>分配足够的内存,然后通过调用适当的构造函数(或非类类型的其他初始化)来初始化它。关于这一点的任何内容都不需要是虚拟的,因为您已明确说明派生类型最多。

new Circle()的结果是指向Circle的指针。将此类型指定给指向Shape的类型指针的变量涉及隐式转换。转换的结果是指向Circle的基础Shape子对象的指针。同样,这一点都不是虚拟的,因为Shape不是虚拟基础,它只是一个常规的基础对象,它在Circle内的位置是静态已知的。

delete s会调用Circle析构函数。这确实使用虚拟调度。编译器知道它正在删除一个Shape,并且Shape的析构函数是虚拟的,因此它会查找相应的析构函数~Circle()并调用它。如果Shape的析构函数不是虚拟的(并且实际上在某处有定义)那么就不会这样做,只会破坏Shape对象,而不是Circle对象,并且释放可能无法正确完成。行为将是未定义的。