Virtual function calling a non-virtual function - c++

I wrote the following piece of code to test my understanding of virtual inheritance. Apparently, I still don't get it fully. Here is my code (followed by my question):
#include <iostream>
#include <vector>
using namespace std;
class Foo
{
public:
virtual void foo();
void foo2();
};
void Foo::foo()
{
cout << "In FOO - foo 1" << endl;
foo2();
}
void Foo::foo2()
{
cout << "In FOO - foo 2" << endl;
}
class Bar : public Foo
{
public:
void foo();
void foo2();
};
void Bar::foo()
{
cout << "In BAR - foo 1" << endl;
foo2();
}
void Bar::foo2()
{
cout << "In BAR - foo 2" << endl;
}
int main()
{
Foo* f = new Foo;
f->foo();
Foo* b = new Bar;
b->foo();
return 0;
}
This is my understanding:
The pointer f points to the base class Foo and f->foo() calls foo() in the base class which in turn calls foo2() in the base class.
The pointer b is a base-class pointer but points to an object of the derived class Bar. Now, since foo() is a virtual function, it calls foo() of the derived class. Now foo() (of the derived class) calls foo2(). Since foo2() is not a virtual function, I was expecting the base class foo2() to get called. However I see that foo2() of the derived class is getting called.
So, I was expecting this output:
In FOO - foo 1
In FOO - foo 2
In BAR - foo 1
In FOO - foo 2
but got this instead:
In FOO - foo 1
In FOO - foo 2
In BAR - foo 1
In BAR - foo 2
Why is this so? From what I understand, the vtable will have an entry only for foo() and not for foo2(). So, how is foo2() of the derived class getting called?
This is my first post. Please excuse me if I have broken any posting guidelines. Thanks in advance!

In Bar::foo(), you are calling foo2(). This is really equivalent to calling this->foo2(). The type of this is Bar, so this is really equivalent to:
void Bar::foo()
{
Bar *bar = this;
bar->foo2();
}
So there's no polymorphism involved at this point; the call is resolved to Bar::foo2 at compile-time, rather than dynamically at run-time.

because Bars foo is what's calling foo2, at that stage it knows its a Bar....
try again, except call foo2 directly in main for both rather than foo calling foo2
int main()
{
Foo* f = new Foo;
f->foo();
f->foo2();
Foo* b = new Bar;
b->foo();
b->foo2();
return 0;
}

how is foo2() of the derived class getting called?
You expect Bar::foo2 to never be called. Then your question can be reformulated as: "why is the purpose of Bar::foo2, if any?"
Its purpose is to be called when dealing with Bar objects. The foo2 of a Bar object is called whenever foo2 is called.
It is only for foo objects that it matters whether Foo::bar2 is virtual or not. Inheritance never forces you to use the functions with the same signature in the base class, if you are dealing directly with derived class objects. (It would cause too many unpleasant surprises to have the inheritance rules work differently in this matter.)
What you have essentially done is hiding. By creating a function with the same signature in Bar, you have hidden the nonvirtual function in the base class Foo. This is typically a bad design because it is unnecessarily complex - it is better to choose different names for different things, to avoid hiding. Hiding is seldom part of a conscious good design.

void Bar::foo()
{
cout << "In BAR - foo 1" << endl;
foo2();
}
This is because Bar::foo2() is the foo2() called by foo(). Bar::foo2() is local to Bar::foo() and has precedence. It's just static dispatch from Bar::foo2().
If the behavior you expected is what you really want, you can choose the method by specifying its scope like so:
void Bar::foo()
{
cout << "In BAR - foo 1" << endl;
Foo::foo2();
}
So this really does not have to do with dynamic dispatch.

Related

Order of static destructors

If a class Foo has a static member variable Bar, I would expect Bar's destructor to run only after the last instance of Foo's destructor runs. This doesn't happen with the code snippet below (gcc 6.3, clang 3.8):
#include <memory>
#include <iostream>
class Foo;
static std::unique_ptr<Foo> foo;
struct Bar {
Bar() {
std::cout << "Bar()" << std::endl;
}
~Bar() {
std::cout << "~Bar()" << std::endl;
}
};
struct Foo {
Foo() {
std::cout << "Foo()" << std::endl;
}
~Foo() {
std::cout << "~Foo()" << std::endl;
}
static Bar bar;
};
Bar Foo::bar;
int main(int argc, char **argv) {
foo = std::make_unique<Foo>();
}
Outputs:
Bar()
Foo()
~Bar()
~Foo()
Why is the order of destruction not the reverse of construction here?
If ~Foo() uses Foo::bar this is a use after delete.
In C++ the objects are constructed in order of occurrence and destructed in the reverse order. First comes foo construction, then bar construction then main is executed then bar is destructed and then foo. This is the behavior you are seeing. The switch appears because the constructor of foo doesn't construct a Foo, it constructs an empty unique_ptr, so you don't get to see Foo() in the output. Then bar is constructed with the output and in main you create the actual Foo after foo has long been constructed.
I would expect Bar's destructor to run only after the last instance of Foo's destructor runs.
No, as a static data member, Foo::bar is independent of any instances of Foo.
And for the code you showed,
static std::unique_ptr<Foo> foo; // no Foo created here
Bar Foo::bar; // Foo::bar is initialized before main(), => "Bar()"
int main(int argc, char **argv) {
foo = std::make_unique<Foo>(); // an instance of Foo is created, => "Foo()"
}
// objects are destroyed in the reverse order how they're declared
// Foo::bar is defined after foo, so it's destroyed at first => "~Bar()"
// foo is destroyed; the instance of Foo managed by it is destroyed too => "~Foo()"
The complication here is that the code doesn’t instrument the constructor of foo. What happens is that foo gets constructed first, than Foo::bar gets constructed. The call to make…unique constructs a Foo object. Then main exits, and the two static objects get destroyed in reverse order of their construction: Foo::bar gets destroyed, then foo. The destructor for foo destroys the Foo object that it points to, which is the one created inmain.
Static objects' lifetimes are based solely on the order of their definition. The compiler doesn't "know enough" when to call Bar::Bar() as much as calling Bar::~Bar().
To illustrate the problem better, consider this
class Foo;
struct Bar {
Bar() {
std::cout << "Bar()" << std::endl;
}
~Bar() {
std::cout << "~Bar()" << std::endl;
}
void baz() {}
};
struct Foo {
Foo() {
bar.baz();
std::cout << "Foo()" << std::endl;
}
~Foo() {
std::cout << "~Foo()" << std::endl;
}
static Bar bar;
};
Foo foo;
Bar Foo::bar;
int main() {}
Prints
Foo()
Bar()
~Bar()
~Foo()
The addition of std::unique_ptr postpones Foo::Foo() after its construction in main, giving the illusion of the compiler "knowing" when to call Bar::Bar().
TLDR Static objects should be defined later than its dependencies. Before defining bar, it is just as much a bug to define a std::unique_ptr<Foo> and to define a Foo
In general, you should not write code which depends on the order of construction or destruction of static (or global) data. This makes unreadable and unmaintainable code (you might prefer static smart pointers, or
explicit initialization or startup routines called from main). And AFAIK that order is not specified when you link several translation units.
Notice that GCC provides the init_priority and constructor (with priority) attributes. I believe you should rather avoid using them. However, the __attribute__(constructor) is useful inside plugins, for plugin initialization.
In some cases, you might also use atexit(3) (at least on POSIX systems). I don't know if such registered functions are called before or after destructors (and I think you should not care about that order).

non virtual method call in a virtual method, C++

Here is the code I'm talking about
#include <stdio.h>
#include <stdlib.h>
class A {
public:
void method() {printf("method A\n");}
virtual void parentMethod() { printf("parentMethod\n"); method(); }
};
class B : public A {
public:
void method() {printf("method B\n");}
};
int main(void) {
A a;
B b;
a.parentMethod();
b.parentMethod();
}
My question is why this is happening? Why when b.parentMethod() is called it doesn't print method B. I realize that it has something to do with method() being in A and B as well as being non-virtual, but I can't get my head around it. Would someone be able to explain this behaviour?
Any help is appreciated.
You code was missing a virtual keyword:
#include <stdio.h>
#include <stdlib.h>
class A {
public:
virtual void method() {printf("method A\n");} // virtual was missing
void parentMethod() { printf("parentMethod\n"); method(); } // unnecessary virtual keyword
};
class B : public A {
public:
void method() {printf("method B\n");}
};
int main(void) {
A a;
B b;
a.parentMethod();
b.parentMethod();
}
The definition in the most upper class must contain the virtual keyword. It is very logical if you think about it. In this case, when you call method() the compiler knows it has to do something more than with a normal function call immediately.
Otherwise, it would have to find and iterate on all the derived types to see if they contain a redefinition of method().
My question is why this is happening? Why when b.parentMethod() is called it doesn't print method B. I realize that it has something to
do with method() being in A and B as well as being non-virtual, but I
can't get my head around it. Would someone be able to explain this
behaviour?
C++ has two levels of indirection when it comes to classes/structures. You have your "plain functions" (including "overloaded", "lambdas", static, etc.) and you have your "virtual functions". First, let's explain "plain functions".
struct Foo {
void goo();
};
In this structure, goo is just a plain old functions. If you try to write it in C, this would be analogous to calling,
void goo(struct Foo *this);
Nothing magical, just a plain function with a "hidden" pointer (all c++ functions have that "hidden" this pointer passed to them). Now, let's re-implement this function in an inherited structure,
struct Goo : public Foo {
void goo();
};
...
Goo g;
g.goo();
Foo f;
f.goo();
Here, plain as day, g.goo() calls goo() in Goo structure, and f.goo() calls goo() in Foo structure. So, in C functions, this would be just,
void goo(struct Foo *this);
void goo(struct Goo *this);
provided C did parameter overloading. But still, just plain functions. Calling goo() in Foo object will call different function than calling goo() in Goo object. Compile time resolution only. But now, let's make our function "virtual"
struct Foo {
virtual void goo();
};
struct Goo : public Foo {
void goo(); // <- also virtual because Foo::goo() is virtual
// In C++11 you'll want to write
// void goo() override;
// which verifies that you spelled function name correctly
// and are not making *new* virtual functions! common error!!
};
...
Goo g;
g.goo();
Foo f;
f.goo();
What happens here is that Foo now contains a "virtual table". The compiler now creates a table of functions that maps location of "latest" goo() function. Namely, implicit Foo() constructor would do something like,
virt_table[goo_function_idx] = &Foo::goo;
and then the constructor in Goo() would update this table with,
virt_table[goo_function_idx] = &Goo::goo;
And then when you have,
Foo *f = new Goo();
f->goo();
what happens is akin to,
f->virt_table[goo_function_idx]();
The function location is looked up in the "virtual table", and that function is called. This means runtime resolution of functions, or polymorphism. And this is how Goo::goo() is called.
Without this table, the compiler can only call functions it knows for said object. So in your example, b.parentMethod() is looked up in the table and called. But method() is not part of that table, so only compile-time resolution is attempted. And since this pointer is A*, you get A::method called.
I hope this clears up the "virtual table" business - it's literally an internal lookup table, but only for functions marked as virtual!
PS. You may ask, "but the this pointer will get 'upcast' by the virtual table from Foo* to Goo*", and yes, it would. I'll leave it as an exercise for you to figure out why that would always be correct.
Well you are correct. This is happening because your method is not virtual. When you are calling it through the parent class, there is no way for it to know, that it was overloaded, so A::method is always called. If you mark method as virtual, then call to it will be routed through the class vtable, so A::method would be replaced by the B::method in the ascendant class.
virtual means that a method can be overridden in a subclass. I think you wanted method, not parentMethod, to be overridden for B. I've renamed parentMethod to foo to be less misleading.
#include <stdio.h>
#include <stdlib.h>
class A {
public:
virtual void method() {printf("method A\n");}
void foo() { printf("foo\n"); method(); }
};
class B : public A {
public:
void method() {printf("method B\n");}
};
int main(void) {
A a;
B b;
a.foo();
b.foo();
}
You'll see that this gives the expected output:
foo
method A
foo
method B
Here's the ideone.

Reference or shared_ptr as member for association

I'm writing a class Bar. Bar needs to access an other class Foo to be useful.
So the instance of Foo has to outlive the instance of Bar using it.
I can't decide between two ways to write this. Here is an example:
#include <iostream>
#include <memory>
using namespace std;
struct Foo {
Foo(int _x) : x_(_x) {}
~Foo() {}
int x_;
};
struct Bar1 {
Bar1(Foo& _foo) : foo_(_foo) {}
void print_foo() {cout << foo_.x_ << endl;}
private:
Foo& foo_;
};
struct Bar2 {
Bar2(shared_ptr<Foo> _foo) : foo_{move(_foo)} {}
void print_foo() {cout << foo_->x_ << std::endl;}
private:
shared_ptr<Foo> foo_;
};
int main()
{
Foo f1{1};
shared_ptr<Foo> f2 = make_shared<Foo>(2);
Bar1 b1(f1);
b1.print_foo();
Bar2 b2(f2);
b2.print_foo();
return 0;
}
I think, that Bar1 gives the user more freedom on how to manage the lifetime of Foo
and it probably is more efficient. But it goes in an undefined (not sure if
this is the right word here) state, when the instance of Foo to which foo_ refers is destroyed.
What is the preferred way to handle a situation like this and why?
I think the preferred way to handle this situation depends on the specifics of the situation. As you identified, Bar1 gives the user more freedom with the lifetime of Foo, and is more dangerous. It is also more efficient (slightly), but probably not enough to be a concern.
If you know for a fact (and/or can prove) that Foo will always outlive all of your Bar objects (maybe you allocate the Foo you use on the stack in main), there is no problem using Bar1. If you are unsure, Bar2 would be the way to go. Though the semantics may be wrong with Bar2 (maybe you don't want Bar to keep your Foo alive).
This leads us to a third option: weak_ptr. This would give the user control of the lifetime of Foo, but still allow Bar to have defined behavior when the Foo is destroyed.
struct Bar3 {
Bar3(std::weak_ptr<Foo> _foo) : foo_(_foo) {}
void print_foo_v1() {
// throws if foo_'s object has been destroyed
std::shared_ptr<Foo> foo(foo_);
std::cout << foo->x_ << std::endl;
}
void print_foo_v2() {
// returns nullptr if foo_'s object has been destroyed
std::shared_ptr<Foo> foo(foo_.lock());
if (foo) {
std::cout << foo->x_ << std::endl;
}
}
private:
std::weak_ptr<Foo> foo_;
};
If you know that Foo will outlive Bar use reference-based solution because of simplicity and because it expresses what you want to achieve - that Bar references Foo. If you use pointers then the intent is not that clear.

Non virtual version of virtual class

Lets say we have the following two class definitions.
#include <iostream>
#include <array>
class A
{
public:
virtual void f() = 0;
};
class B : public A
{
public:
virtual void f() { std::cout << i << std::endl; }
int i;
};
Here sizeof(B) == 8, presumably 4 the virtual pointer and 4 for the int.
Now lets say we make an array of B, like so:
std::array<B, 10> x;
Now we get sizeof(x) == 80.
If my understanding is correct, all method calls on elements of x are resolved statically, as we know the type at compile time. Unless we do something like A* p = &x[i] I don't see a need to even store the virtual pointer.
Is there a way to create an object of type B without a virtual pointer if you know it is not going to be used?
i.e. a template type nonvirtual<T> which does not contain a virtual pointer, and cannot be pointed to by a subtype of T?
Is there a way to create an object of type B without a virtual pointer if you know it is not going to be used?
No. Objects are what they are. A virtual object is virtual, always.
After all, you could do this:
A *a = &x[2];
a->f();
That is perfectly legitimate and legal code. And C++ has to allow it. The type B is virtual, and it has a certain size. You can't make a type be a different type based on where it is used.
Answering my own question here, but I've found that the following does the job, by splitting A into it's virtual and non-virtual components:
enum is_virtual
{
VIRTUAL,
STATIC
};
template <is_virtual X>
class A;
template<>
class A<STATIC>
{
};
template<>
class A<VIRTUAL> : public A<STATIC>
{
public:
virtual void f() = 0;
virtual ~A() {}
};
template <is_virtual X>
class B : public A<X>
{
public:
void f() { std::cout << i << std::endl; }
int i;
};
The important thing here is that in B<> don't specify f() as virtual. That way it will be virtual if the class inherits A<VIRTUAL>, but not virtual if it inherits A<STATIC>. Then we can do the following:
int main()
{
std::cout << sizeof(B<STATIC>) << std::endl; // 4
std::cout << sizeof(B<VIRTUAL>) << std::endl; // 8
std::array<B<STATIC>, 10> x1;
std::array<B<VIRTUAL>, 10> x2;
std::cout << sizeof(x1) << std::endl; // 40
std::cout << sizeof(x2) << std::endl; // 80
}
That would be a nice one to have, but I can't think of any way to revoke virtual members or avoid storing the virtual pointer.
You could probably do some nasty hacks by keeping a buffer that's the size of B without the virtual pointer, and play with casts and such. But is all undefined behavior, and platform dependant.
Unfortunately it won't work in any normal sense as the code inside the method calls expects the virtual pointer to be in the class definition.
I suppose you could copy/paste all of A and B's code into a new class but that gets to be a maintenance headache fast.

C++ Do I Understand Polymorphism Correctly?

Bar and Box are derived classes of Foo and Foo has a virtual function F() and Bar and Box both have function F(). From what I understand, polymorphism correctly allows Bar.F() instead of Box.F() or Box.F() instead of Bar.F() to override Foo.F() using some runtime routine without knowing whether your object is a Bar or a Box. It's something like this:
Foo * boxxy = new Box;
boxxy->F();
The last line will call the right F() (in this case, Box.F()) independent of whether boxxy is a Box or a Bar or a Foo (in which case the implementation of the virtual Foo.F() is called).
Do I understand this right? And what changes if boxxy is a Box pointer? And what happens if the derived class doesn't have an override for F()? Lastly, to avoid implementing a function for a base class but still allow polymorphism, do you just write an empty function body and declare it virtual? Thanks.
Nearly right - consider this inheritance tree:
Foo
/ \
Bar Box
If you now make a pointer like this:
Bar* barry = new Box();
You'll get a nice compiler error, since a Box can't be converted to a Bar. :)
So it's only Foo<->Bar and Foo<->Box, never Bar<->Box.
Next, when boxxy is a Box pointer, it will only ever call the Box::F function, if it is provided.
And last, to force subclasses to implement a certain function, you declare it pure virtual, like this:
virtual void Func() = 0;
// note this --- ^^^^
Now subclasses (in this case Bar and Box), must implement Func, else they will fail to compile.
Yes the right F() will be called dependent on the type of object you have created through your Foo pointer.
If boxxy were a Box pointer you could only call it's F() or one of it's derived class's F(), unless you did a dynamic_cast to it's parent class and then called F().
To avoid having to implement in the base class you define it as pure virtual like so:
class Foo
{
public:
virtual void F() = 0; //notice the = 0, makes this function pure virtual.
};
And what changes if boxxy is a Box
pointer?
It will allow access to the methods of Box not inherited from Foo. Box pointer can't point to Bar objects, since Bar isn't derived from Box.
And what happens if the derived class
doesn't have an override for F()?
It will inherit the implementation of F() from the base class.
Lastly, to avoid implementing a
function for a base class but still
allow polymorphism, do you just write
an empty function body and declare it
virtual?
It will work, but it is not a right way to do polymorphism. If you can't come up with a concrete implementation for the virtual function of the base class make that function pure virtual, don't implement it as empty function.
If you declare Foo like this
class Foo
{
private:
Foo() {};
public:
void func() const { std::cout << "Calling Foo::func()" << std::endl; }
};
and Bar like this
class Bar : public Foo
{
private:
Bar() {};
public:
void func() const { std::cout << "Calling Bar::func()" << std::endl; }
};
then
Foo* bar = new Bar();
bar->func();
will call Foo::func().
If you declare Foo like this
class Foo
{
private:
Foo() {};
public:
virtual void func() const { std::cout << "Calling Foo::func()" << std::endl; } // NOTICE THE virtual KEYWORD
};
then
Foo* bar = new Bar();
bar->func();
will call Bar::func().
Do I understand this right? Yes, if the function was declared as a virtual function.
And what changes if boxxy is a Box
pointer? Depends on whether the
function is virtual or not. A virtual
function will always end up calling
the proper derived function; a
non-virtual function will call the
version based on the type of the
pointer.
And what happens if the derived class
doesn't have an override for F()? It
will use the base class definition.
Lastly, to avoid implementing a
function for a base class but still
allow polymorphism, do you just write
an empty function body and declare it
virtual? You can also declare it pure
virtual: virtual void F() = 0. Any
class that intends to be instantiated
into an object much override this
function and give it a proper
implementation.