0

Possible Duplicate:
Why does an overridden function in the derived class hide other overloads of the base class?

Hi,

Let me explain my question with this example :

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 ?
}

This brings me to ask two questions :

  1. Which destructor is called when using delete on an abstract-base-class pointer ?
  2. Is it possible to make a copy of my object "a" with one of the copy methods above ?
Community
  • 1
  • 1
Jack
  • 87
  • 2
  • 7
  • you want a pure virtual destructor? – Mare Infinitus Jul 18 '12 at 19:24
  • I think the question does not make much sense. First of all, the object is of type B, and thanks to being virtual, the correct destructor of B will be called (no question about that, regardless of what type the pointer is). However, then the destructor of the base class A will be invoked as well according to standard object creation/destruction rules, and since it does not exist, the compiler will bail out. – Damon Jul 18 '12 at 19:29
  • I agree with @Damon. Question 1. effectively asks how do virtual functions work. As for question 2. that's been asked before eg. [here](http://stackoverflow.com/questions/4032109/copy-constructor-needs-to-call-a-method-that-depends-on-the-object-but-construc) and [here](http://stackoverflow.com/questions/669818/virtual-assignment-operator-c). – Troubadour Jul 18 '12 at 20:00
  • @Damon: What do you mean by "does not exist" and "compiler will bail out"? The destructor obviously exists. It is defined by `{}` (even though the placement is non-standard). – AnT stands with Russia Jul 18 '12 at 20:13
  • @Troubadour Sorry if it was already asked, and thanks for the links – Jack Jul 18 '12 at 21:12
  • @AndreyT: The destructor does not exist because it's a pure declaration without definition. The `{}` is apparently a typo, or it's... whatever(?), in any case it's not valid C++. A pure-specifier on function-definition is not allowed. Thus, since the destructor has not been defined, it doesn't exist, and the compiler will find that it's attempting to call a non-defined function. Therefore it will abort with an error ("bail out"). – Damon Jul 19 '12 at 09:22
  • @Damon: Well, allowing in-class definitions for pure virtual functions is something some compilers allow as an extension. Since the OP used that syntax, it is probably safe to assume that OP's compiler allows it. A pedantic compiler will, of course, complain about it, but the complaint would most likely be about the invalid syntax around destructor declaration, not the "missing definition". – AnT stands with Russia Jul 19 '12 at 14:46

4 Answers4

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Yes that is what I would like to do, but obviously it is not as simple and clear as I expected. I will rather try to change a bit the behaviour of my classes. – Jack Jul 18 '12 at 21:08
0
virtual ~A() = 0 { }

This is not going to compile. A pure virtual destructor will look like:

virtual ~A() = 0;

Even so, you will have to add an implementation, because all the destructors of the class heirarchy will be called when destructing an object. So, if you will not implement the body, this will cause UB (or it will not even compile as it doesn't for me with gcc 4.6.3).

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
0

1: ~B() is called through the virtual ~A() = 0; the implementation of ~A() is then called by ~B().

Also, virtual ~A() = 0 { } is incorrect syntax; you have to write virtual ~A() = 0; and then supply inline A::~A() { } outside the class definition.

2: Your code won't compile because B::operator=(const B&) is not an acceptable override for A::operator=(const A&) = 0; only function return types are allowed to be covariant for virtual methods.

There is no easy way to copy a polymorphic object through copy constructor or assignment operator, since such a member would have to use double dispatch (see virtual assignment operator C++). The usual method is to have a virtual A *clone() = 0 function, which is expected to return a new instance of the derived class.

Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366
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)