0

可能重复:
为什么派生类中的重写函数隐藏了基类的其他重载?

你好,

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

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

4 回答 4

2
  1. Both are called.

    In delete a the derived class destructor ~B::B is found and called using the virtual dispatch mechanism. The implementation of ~B::B in turn implicitly calls the base class destructor ~A::A. However, this call is implemented as non-virtual ordinary call, meaning it is not affected by the fact that ~A::A is declared as pure.

    This is actually the reason why pure virtual destructors still have to be defined. Although the language specification does not permit in-class definitions for pure virtual functions. Even if you want it to be inline, you still have to define it out of class.

  2. It is not possible to copy a standalone object of type A simply because there can't be any standalone object of abstract type. Please, clarify your question. What do you want to copy and to where?

    If you want to do something like this

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

    and expect the last assignment to behave as if b1 = b2 was performed... well, it can be done but it will take some effort and might/will result in pretty ugly code. I'd say that burdening the overloaded assignment operator with that sort of functionality is not a good idea.

于 2012-07-18T20:01:59.387 回答
0

1) The destructor ~B() is called first, after the destructor ~A(), remember just that's:

Where the constructor have been call, the destructor will be call at reverse order.

2) yes, because it's pointer, the heritage can block the copy (contructor by recopy)

于 2012-07-18T19:59:09.550 回答
0
virtual ~A() = 0 { }

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

virtual ~A() = 0;

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

于 2012-07-18T19:28:14.633 回答
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。对于虚方法,只有函数返回类型允许是协变的。

没有简单的方法可以通过复制构造函数或赋值运算符来复制多态对象,因为这样的成员必须使用双重调度(参见虚拟赋值运算符 C++)。通常的方法是拥有一个virtual A *clone() = 0函数,该函数期望返回new派生类的一个实例。

于 2012-07-18T19:29:52.397 回答