C ++如何为基类类对象调用纯虚方法?

时间:2012-07-18 19:21:24

标签: c++ copy polymorphism destructor

  

可能重复:
  Why does an overridden function in the derived class hide other overloads of the base class?

您好,

让我用这个例子解释我的问题:

class A
{
    virtual ~A() = 0 { }

    A(const A&);
    virtual void operator =(const A&) = 0;
}

class B : public A
{
    ~B();

    B(const B&);
    void operator =(const B&);
}

void main(void)
{
    A* a = new B();
    delete a; // Is ~A() called, ~B() or both ?
}

这让我提出两个问题:

  1. 在抽象基类指针上使用delete时调用哪个析构函数?
  2. 是否可以使用上述复制方法之一复制我的对象“a”?

4 个答案:

答案 0 :(得分:2)

  1. 两者都被称为。

    delete a中,使用虚拟调度机制找到并调用派生类析构函数~B::B~B::B的实现依次隐式调用基类析构函数~A::A。但是,此调用是作为非虚拟普通调用实现的,这意味着它不会被~A::A声明为纯粹的事实所影响。

    这实际上是为什么仍然需要定义纯虚拟析构函数的原因。虽然语言规范不允许纯虚函数的类内定义。即使你希望它是内联的,你仍然需要在课堂上定义它。

  2. 由于不能有任何抽象类型的独立对象,因此无法复制A类型的独立对象。请澄清你的问题。你想复制什么,到哪里去?

    如果你想做这样的事情

    B b1, b2;
    A *a1 = &b1, *a2 = &b2;
    
    *a1 = *a2;
    

    并期望最后一次分配的行为就像执行b1 = b2一样......好吧,它可以完成,但需要花费一些精力,而且可能/会导致相当丑陋的代码。我会说使用这种功能给重载的赋值操作符加载负担并不是一个好主意。

答案 1 :(得分:0)

virtual ~A() = 0 { }

这不会编译。纯虚拟析构函数如下所示:

virtual ~A() = 0;

即使这样,你也必须添加一个实现,因为 all 在破坏对象时会调用类层次结构的析构函数。所以,如果你不实现主体,这将导致UB(或者它甚至不会编译,因为gcc 4.6.3不适合我。)

答案 2 :(得分:0)

1:~B()通过虚拟~A() = 0调用;然后~A()调用~B()的实现。

此外,virtual ~A() = 0 { }语法不正确;你必须写virtual ~A() = 0;然后在类定义之外提供inline A::~A() { }

2:您的代码无法编译,因为B::operator=(const B&)不是A::operator=(const A&) = 0的可接受覆盖;只允许函数返回类型为虚方法协变。

通过复制构造函数或赋值运算符复制多态对象没有简单的方法,因为这样的成员必须使用双重调度(请参阅virtual assignment operator C++)。通常的方法是使用virtual A *clone() = 0函数,该函数应返回派生类的new实例。

答案 3 :(得分:0)

1)首先在析构函数~A()之后调用析构函数~B(),记住它的:

  

在构造函数被调用的地方,析构函数将被调用   逆序。

2)是的,因为它是指针,遗产可以阻止复制(通过重新复制构造)