C++ interview inheritance puzzle [duplicate] - c++

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ virtual function from constructor
Calling virtual functions inside constructors
This question was asked in interview .
I guess I had answered the 1st part correctly but not sure about the 2nd part. In fact I have no clue about 2nd part.
What output does the following code generate? Why?
What output does it generate if you make A::Foo() a pure virtual function?
When I tried running same question on my compiler with virtual void foo() = 0; it throws
error "undefined reference to `A::Foo()'"
#include <iostream>
using namespace std;
class A
{
public:
A()
{
this->Foo();
}
virtual void Foo()
{
cout << "A::Foo()" << endl;
}
};
class B : public A
{
public:
B()
{
this->Foo();
}
virtual void Foo()
{
cout << "B::Foo()" << endl;
}
};
int main(int, char**)
{
B objectB;
return 0;
}

When you instantiate a B object, the following happens:
B's constructor is called.
First thing, B's constructor calls the base constructor A().
Inside A's constructor, the function call is dispatched to A::foo(), since this has static and dynamic type A* (nothing else makes sense if you think about it); now the A subobject is complete.
Now B's constructor body runs. Here the function call is dispatched to B::foo(). Now the entire B object is complete.
If A::foo() is pure-virtual, step (3) causes undefined behaviour; cf. 10.6/4 in the standard.
(In your case possibly manifesting as a linker error, since the compiler optimizes to resolve the call statically, and the symbol A::foo is not found.)

In the second case you have undefined behavior (calling a pure virtual of class T in a class T constructor), so the output could be anything – if it even compiles.
The main thing to understand is that in C++, the dynamic type of an object is T when an object's T constructor executes.
This makes it safe to call virtual functions from a C++ constructor. You don't get a call down into an uninitialized derived class sub-object. In contrast, in Java and C# (and similar languages) you can easily get that kind of bug, and it's common.

Constructors will be called so that the parents are constructed first, so that there won't be any dependencies on undefined objects. Thus it's A::A followed by B::B. Edit: It's also possible that B's constructor calls A's directly, as Kerrek SB says - the end effect is the same.
In the first case, the output will be "A::Foo()" followed by "B::Foo()". At the time of A's construction B doesn't exist yet, and its virtual functions aren't yet part of the object.
In the second case, you'll be calling a pure virtual function A::Foo which will generate a fault or refuse to compile altogether.

Methods in constructors are dispatched as the dynamic type of the class. A's constructor is calling Foo with dynamic type A. (see AlfP.Steinbach's comment for the correct definition)
If A is an abstract base then the error is because it's trying to call a pure virtual method.
A()
{
this->Foo(); // call A::Foo
}
From Effective C++ by Scott Meyers:
There's a good reason for this seemingly counterintuitive behavior. Because base class constructors execute before derived class constructors, derived class data members have not been initialized when base class constructors run. If virtual functions called during base class construction went down to derived classes, the derived class functions would almost certainly refer to local data members, but those data members would not yet have been initialized. That would be a non-stop ticket to undefined behavior and late-night debugging sessions. Calling down to parts of an object that have not yet been initialized is inherently dangerous, so C++ gives you no way to do it.

Related

What happens when a destructor calls an abstract function

I'm having trouble understanding what's the reason for the crash in the following code :
class A {
public:
virtual ~A() { goo(); }
void goo() { absFoo(); }
virtual void absFoo() = 0;
};
class B : public A {
public:
void absFoo() { cout << "In B \n"; }
};
int main()
{
B b1;
b1.goo();
}
The main prints "In B" as expected, but in the end when it crashes, I can't debug it either, the compiler pops a weird message.
So my question is, when the destructor of A calls "goo()", does "absFoo()", crash
because we're referring to an abstract function?
Or does the compiler actually look for a definition in the derived classes? (And it doesn't exist anymore because it was destructed beforehand so it crashes)
I know that if we had called "absFoo()" directly from the destructor, the reason would have been the abstract function. But since here it's an outside function calling "absFoo()" I'm having trouble understanding the real reason.
What happens when a destructor calls an abstract function
First, let us consider what happens when a destructor calls any virtual function (the same applies to the constructor by the way): When a virtual function foo is called in the destructor of T, the call will not be dispatched dynamically to an implementation in a derived type (the lifetime of any derived object has already ended), but statically to the implementation T::foo.
If T::foo is pure virtual, then calling it without dynamic dispatch will have undefined behaviour. That is what happens when a pure virtual function is (indirectly) called in a destructor (or constructor).
Just to complement the already accepted answer, this is the documentation from cppreference.
When a virtual function is called directly or indirectly from a
constructor or from a destructor (including during the construction or
destruction of the class’s non-static data members, e.g. in a member
initializer list), and the object to which the call applies is the
object under construction or destruction, the function called is the
final overrider in the constructor’s or destructor’s class and not one
overriding it in a more-derived class.
In other words, during construction or destruction, the more-derived classes do not exist.
As the object is deconstructed, the vtable is updated to match the new status of the object.
Since you've removed the last function, the compiler will do whatever it considers fit; which in the case of a debug compilation in visual studio, will fallback to an abort reporting that a pure virtual function was called.
The vtable however is not part of the standard, it's an implementation detail, and there's no requirement for your program to crash; it's just what is considered the nicest thing to do when you've called a pure virtual function.

How "virtual" impact on destructor in C++?

Virtual function from official explanation is:
A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.
Please see the code first:
#include<iostream>
using namespace std;
class A
{
public:
A(){cout << "A()" << endl;}
~A(){cout << "~A()" << endl;}
};
class B:public A
{
public:
B(): A(){cout << "B()" << endl;}
~B(){cout << "~B()" << endl;}
};
int main()
{
A * pt = new B;
delete pt;
}
Output is:
A()
B()
~A()
My question is:
Destructor of base class can't be inherited by derived class, so why we make destructor of base class to be virtual?
For the code above, I know this will lead to problem(here destructor of class B not called). I have searched so many articles or questions from google and stackoverflow and all of them tell me that destructor of base should be virtual but how "virtual" on destructor works? I mean that what the difference in core code level with/without "virtual" to the destructor?
delete pt; causes undefined behaviour if the destructor of A is not virtual.
The reason to make A's destructor virtual is to enable the use of delete pt; to delete a B object.
The rationale for this is that when the compiler sees delete pt;, in general, it has no way of knowing whether pt points to a B object or not, since that decision could have not been made until run-time. So you need to look up some run-time property of the object (in this case a vtable) to find out the right destructor to call.
Some other comments/answers suggest that the defined behaviour of your original code is to not call B's destructor , or something. However that is wrong. You are just seeing symptoms of undefined behaviour, which could be that or anything else.
If the destructor is marked virtual then when you call delete the destructor of the dynamic type of the object you have allocated will be called. In your example the static type of the object on the heap is A, whereas the dynamic type is B.
Since you have not marked the destructor virtual, there will be no run time dispatch and the destructor for A is called. This is wrong and should be fixed. If you are planning on using a class in a polymorphic way, make sure it's destructor is virtual, so that instances of the derived classes can release any resources they have acquired.
It can help to imagine how vtables are implemented.
A class with a virtual method has a pointer to a table of function pointers as its first element.
virtual on a method means there is an entry in the virtual function table for it.
For a method, inherited classes replace the entry when they override.
For destructors the entry is actually "how to call delete on this object". All descended classes automatically override it. It turns a call of delete base_ptr into if (base_ptr) base_ptr->vtable->deleter(base_ptr); conceptually.
Then the deleter of derived is effectively (almost) delete static_cast<derived*>(ptr); That does what a usual call to delete does, it calls the destructors in order.
Failing to do that leaves you with undefined behaviour. Often the UB is that the base class dtor is called.
If the function is not virtual, the C++ runtime will directly call the mangled function. For example, in the above code, the destructor may be mangled as _ZNK3AXXXXXXXXX (fake name). So when you call delete pt, the runtime will execute _ZNK3AXXXXXXXXX.
However, the result is different if the function is virtual. Like #Yakk said, a class with virtual functions will have a vtable, whose entries are function pointers. It may be at the top of the address space of this class, or at the bottom, depending on the implementation of class model. Any call of virtual function will look up this table. If the dtors are virtual, the function in derived class will override the corresponding entry in the table. When you call it using a pointer or reference, the C++ runtime will call the function in the table. Look at your example again. The entries of object pointed by pt have been overrode by class B, so when you call delete pt, the overrode version of dtor will be invoke. That's is the difference.

Calling a virtual function from the constructor

I'm reading Effective C++, and there is the "Item 9: Never call virtual functions during construction or destruction". And I'm wondering if my code is fine even if it breaks this rule:
using namespace std;
class A{
public:
A(bool doLog){
if(doLog)
log();
}
virtual void log(){
cout << "logging A\n";
}
};
class B: public A{
public:
B(bool doLog) : A(false){
if(doLog)
log();
}
virtual void log(){
cout << "logging B\n";
}
};
int main() {
A a(true);
B b(true);
}
Is there something wrong with this approach? May I get in trouble when I do something more complicated?
It seams to me that most answers didn't get what I did there, and they simply explained again why is calling virtual function from constructor potentially dangerous.
I would like to stress out that output of my program looks like this:
logging A
logging B
So I get A logged when it is constructed and B logged when it is constructed. And that is what I want! But I'm asking if You find anything wrong(potentially dangerous) with my "hack" to overcome the problem with calling virtual function in constructor.
Is there something wrong with this approach?
Answer from Bjarne Stroustrup:
Can I call a virtual function from a constructor?
Yes, but be careful. It may not do what you expect. In a constructor,
the virtual call mechanism is disabled because overriding from derived
classes hasn't yet happened. Objects are constructed from the base up,
"base before derived". Consider:
#include<string>
#include<iostream>
using namespace std;
class B {
public:
B(const string& ss) { cout << "B constructor\n"; f(ss); }
virtual void f(const string&) { cout << "B::f\n";}
};
class D : public B {
public:
D(const string & ss) :B(ss) { cout << "D constructor\n";}
void f(const string& ss) { cout << "D::f\n"; s = ss; }
private:
string s;
};
int main()
{
D d("Hello");
}
the program compiles and produce
B constructor
B::f
D constructor
Note not D::f. Consider what would happen if the rule were different so that D::f() was called from B::B(): Because the constructor D::D() hadn't yet been run, D::f() would try to assign its argument to an uninitialized string s. The result would most likely be an immediate crash.
Destruction is done "derived class before base class", so virtual functions behave as in constructors: Only the local definitions are used - and no calls are made to overriding functions to avoid touching the (now destroyed) derived class part of the object.
For more details see D&E 13.2.4.2 or TC++PL3 15.4.3.
It has been suggested that this rule is an implementation artifact. It is not so. In fact, it would be noticeably easier to implement the unsafe rule of calling virtual functions from constructors exactly as from other functions. However, that would imply that no virtual function could be written to rely on invariants established by base classes. That would be a terrible mess.
And I'm wondering if mine code is fine even if it breaks this rule:
It depends on what you mean by "fine". Your program is well-formed, and its behavior is well-defined, so it won't invoke undefined behavior and stuff like that.
However, one may expect, when seeing a call to a virtual function, that the call is resolved by invoking the implementation provided by the most derived type which overrides that function.
Except that during construction, the corresponding sub-object has not been constructed yet, so the most derived subobject is the one currently being constructed. Result: the call is dispatched as if the function were not virtual.
This is counter-intuitive, and your program should not rely on this behavior. Therefore, as a literate programmer, you should get used to avoid such a pattern and follow Scott Meyer's guideline.
It's "fine" in the sense of being well-defined. It may not be "fine" in the sense of doing what you expect.
You will call the override from the class currently being constructed (or destroyed), not the final override; since the final derived class has not yet been constructed (or has already been destroyed) and so can't be accessed. So you may get in trouble if you wanted the final override to be called here.
Since this behaviour is potentially confusing, it's best to avoid having to do it. I would recommend adding behaviour to a class by aggregation rather than subclassing in that situation; the class members are constructed before the constructor body, and last until after the destructor, and so are available in both those places.
One thing you mustn't do is call a virtual function from the constructor or destructor if it's pure virtual in that class; that's undefined behaviour.

calling a protected virtual method in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Calling virtual method in base class constructor
Calling virtual functions inside constructors
How can I call a protected virtual method from a constructor in C++?
class Foo
{
Foo(){
printStuff(); // have also tried this->printStuff()
}
protected:
virtual void printStuff() {}
}
class ExtendedFoo : public Foo {
protected:
virtual void printStuff() { cout << "Stuff" << endl;}
}
...
ExtendedFoo exFoo; // should print "Stuff"
There's no problem in calling a protected function from the constructor - just do it. However, what you seem to be wanting is to call into a concrete derived class' implementation of it, e.g., ExtendedFoo's, since it's virtual - right? That's a no-go, since inside the Foo constructor, the object being created is still of type Foo, not ExtendedFoo, so no virtual dispatch can take place. If the protected function isn't pure virtual, the Foo implementation is called, i.e., the constructor will call the class' own implementation.
Consider that when your base constructor is called, your actual constructor still does not, so you object is not completely formed.
If your object isn't yet formed, you can't expect it to act correctly.
Please read this:
Never Call Virtual Functions during Construction or Destruction.
[10.7] Should you use the this pointer in the constructor?
You can, but you will get Foo's implementation because ExtendedFoo's not been constructed. This is defined.
Similar problem: C++ design pattern: multiple ways to load file
Answer deprecated after question change:
If it is protected in ExtendedFoo, you can not call it from outside of ExtendedFoo. The line...
exFoo.printStuff();
violated the function's protection level.
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr129.htm

When is it safe to call a virtual function in a constructor

I have some code where I really want to call a virtual method from a constructor. I know this is considered unsafe, and I know enough about object construction to also understand why. I also am not experiencing these problems. Currently my code is working and I think it should be fine, but I want to make sure.
Here is what I am doing:
I have some class hierarchy and there is a normal public function which just forwards to a private virtual method, as usual. However I do want to call this public method upon construction of my objects, because it is filling all data into the object. I will be absolutely sure that this virtual call comes from the leaf class, because using this virtual method from any other part of the class hierarchy simply does not make sense at all.
So in my opinion the object creation should be finished once I am doing the virtual call and everything should be fine. Is there still anything that could go wrong? I guess I'll have to mark this part of the logic with some big comments to explain why this logic should never ever be moved to any of the base clases, even though it looks like it could be moved. But other than stupidity of other programmers I should be fine, shouldn't I?
It is absolutely safe to call any non-abstract virtual function in the constructor or the destructor! However, its behavior may be confusing as it may not do what is expected. While the constructor of a class is executed, the static and dynamic type of the object is the type of the constructor. That is, the virtual function will never be dispatched to the override of a further derived class. Other than that, virtual dispatch actually works: e.g. when calling a virtual function via a base class pointer or reference correctly dispatches to the override in the class being currently constructor or destructed. For example (probably riddled with typos as I currently can't this code):
#include <iostream>
struct A {
virtual ~A() {}
virtual void f() { std::cout << "A::f()\n"; }
void g() { this->f(); }
};
struct B: A {
B() { this->g(); } // this prints 'B::f()'
void f() { std::cout << "B::f()\n"; }
};
struct C: B {
void f() { std::cout << "C::f()\n"; } // not called from B::B()
};
int main() {
C c;
}
That is, you can call a virtual function, directly or indirectly, in the constructor or a destructor of a class if you don't want the virtual function to be dispatched to a further derived function. You can even do this is virtual function is abstract in the given class as long as it is defined. However, having an undefined abstract function being dispatched to will cause a run-time error.
When a constructor is called, the class is set up to be an instance of that class but not the derived class. You cannot call into a virtual function of a derived class from a base constructor. By the time you get to the constructor of the most derived class, all of the virtual functions should be safe to call.
If you wish to ensure that someone can't make an incorrect call, define the virtual function in the base class and have it assert and/or throw an exception when it is called.
The rule isn't so much that you need to be in a leaf class as to realize that when you make a member call from Foo::Foo(..), the object is exactly a Foo, even if it's on its way to being a Bar (assuming Foo is derived from Bar and you're constructing a Bar instance). That's 100% reliable.
Otherwise, the fact that the member is virtual isn't all that significant. There are other pitfalls that happen just as well with non-virtual functions: if you were to call a virtual or non-virtual method that assumed the object was completely constructed but called it within the constructor before that was the case, you'd also have problems. These are just hard cases to pin down because not only must the function you call be okay, all the functions it calls must be okay.
It doesn't sound like you have a problem, it's just one of those places prone for errors to crop up.