class base{
public:
virtual void foo(){
std::cout << "base::foo was called" << std::endl;;
}
void bar(){
foo();
std::cout << "base::bar was called" << std::endl;;
}
};
class derived : public base {
public:
void foo() {
std::cout << "derived::foo was called" << std::endl;
}
};
int main() {
derived der;
der.bar();
// desired output = "base::foo was called" "base::bar was called"
// actual output = "derived::foo was called" "base::bar was called"
}
Am I missing something obvious here?
Why does the bar() function when called on an object of derived class call the derived::foo function, even though the function itself only exists in the base class.
When a member function in a derived class overrides a virtual member function in a base class like this, that means it entirely replaces the function definition for most purposes. So calling the function foo on the object der created in main will usually use the Derived::foo definition. This behavior is consistent whether the code calling foo is in a member of Derived, or a member of Base, or neither class.
The two major exceptions are:
If you use a "qualified-id" class_type::func_name syntax to call the function, that disables the virtual function logic and just calls the function you named (after normal name lookup and overload resolution).
So since you say you want the program to call base::foo, change base::bar like:
void bar() {
base::foo();
std::cout << "base::bar was called" << std::endl;
}
During a constructor or destructor of the base class, the function from the base class (or one of its bases) will be called, ignoring overriders in the derived class(es). The object is considered to not yet or no longer be an object of the derived type. (And if the derived function were called and uses any derived members which are not yet created or already destroyed, this would be trouble.)
base::foo is declared virtual, hence uses virtual dispatch. If you don't want that then call base::foo explicitly:
struct base{
virtual void foo(){
std::cout << "base::foo was called" << std::endl;;
}
void bar(){
base::foo();
std::cout << "base::bar was called" << std::endl;;
}
};
(note that all methods are private in your example, I suppose thats just a typo)
When you declare a function virtual, the compiler will generate a vtable for each object created, and in your case, since the object is a derived the function vtable will always point to derived::foo() for that instance.
Related
Suppose I have the following code
class A{
public:
void f1()
{
/*
* Other functions that happen here.
* These calls needs to be made at A's f1() function
* And cannot be in derived class.
*/
f2();
}
virtual void f2()
{
std::cout << "I am base class" << std::endl;
}
};
class B : A
{
public:
void f2()
{
std::cout << "I am derived class" << std::endl;
}
void f3()
{
A::f1();
}
};
int main()
{
B b;
b.f3();
return 0;
}
The output above is
I am derived class
The limitation I have here is that I can't change class A in any way.
Another limitation is that f2() needs to be called through f1(). A::f3() cannot call f1(). The call to f1() needs to be made to A since A's f1() does other things and B cannot override it.
Is there a way to force A::f2() be called when B::f3() is called? In other words, when we ask for the base version, how do we enforce all other functions called within the base class, to use the base version. In this example, that would be f2().
The question marked as duplicate is simply asking to call a parent function from a derived function with no other functions in the called function that overwritten.
Please note that a static cast of A to call f1 will result in the derived class's f2 function to be called.
So I have these classes:
class Base {
public:
Base() {cout << "made a base" << endl;}
virtual void getType() const { cout << "Im a base" << endl;
virtual ~Base() {}
//other members...
}
class Derived: public Base {
public:
Derived() {cout << "made a derived" << endl;
virtual void getType() const { cout << "Im a derived" << endl; }
virtual ~Derived() {}
//other memebrs...
}
int main() {
Base* test = new Derived();
test->getType();
return 0;
}
output:
made a base
made a derived
Im a derived
Now I know that the output is Im a derived because of polymorphism, however I would like to know how this works internally with Vftables, how can It call the correct function, the vtable inside test points to the Base class getType() function because of the type of test so how can it know that it is Derived::getType() and not Base::getType().in other words what does my program do at runtime when it see's this declaration test->getType()?
Thanks in advance.
When you do Base* test = new Derived():
The V-Table pointer of object test is set to point to the V-Table of class Derived.
Note that when the object is created - via new Derived() - you are explicitly calling a function (the constructor) of class Derived and not of class Base.
And when this function is called, it sets the v-table pointer of the new object to point to the V-Table of class Derived and not of class Base.
AFAIK, the actual V-Tables (of both classes), are generated by the linker past compilation.
Supplemental:
The program doesn't need to "know" that a function is virtual.
In case of a non-virtual function call, the compiler adds a JUMP instruction to a constant address (i.e., the address of the non-virtual function, which is resolvable during compilation).
In case of a virtual function call, the compiler adds a JUMP instruction to an address stored in (pointed by) a variable, whose value is resolved only during runtime.
I'm experimneting with inheritance in C++.
struct A {
virtual void foo(){ std::cout << "foo()" << std::endl; }
void bar(){ std::cout << "bar()" << std::endl; }
};
struct B : A{
void foo(){ std::cout << "derived foo()" << std::endl; }
void bar(){ std::cout << "derived bar()" << std::endl; }
};
struct C : B {
void foo(){ std::cout << "derived derived foo()" << std::endl; }
void bar(){ std::cout << "derived derived bar()" << std::endl; }
};
int main()
{
B* b = new C();
b->foo(); //derived derived foo()
b->bar(); //derived bar()
}
LIVE DEMO
Since, the function foo declared as non-virtual in the struct B I expected that B's function would be called. But foo which one from C was. Why? I change the "virtual status" of the function in B. Why is it still virtual?
foo() is declared as virtual function in the base class A, so foo() in all the derived class will be virtual too.
From the standard, 10.3$2 Virtual functions [class.virtual] (bold by me)
If a virtual member function vf is declared in a class Base and in a
class Derived, derived directly or indirectly from Base, a member
function vf with the same name, parameter-type-list (8.3.5),
cv-qualification, and ref-qualifier (or absence of same) as Base::vf
is declared, then Derived::vf is also virtual (whether or not it is so
declared) and it overrides Base::vf.
Once virtual always virtual.
Since foo is virtual in A it will be virtual in all classes derived from A - whether or not they get the virtual keyword.
Above mention answers are valid, but can we use override keyword, because
The override special identifier means that the compiler will check the
base class(es) to see if there is a virtual function with this exact
signature. And if there is not, the compiler will indicate an error.
so something like this is struct B:
void bar() override
Suppose I have
struct C {
C() { init(); };
void init() { cout << "C" << endl; };
};
struct D : public C {
D() : C() { };
void init() { cout << "D" << endl; }
};
D();
why I get "C" printed? How can change this behaviour (and get "D").
How if I want both?
why I get "C" printed?
C::init() is not declared as virtual, so D cannot override it. But even if C::init() were declared as virtual, D::init() would still not be called when init() is called inside of C's constructor.
C++ constructs base classes before derived classes (and destructs derived clases before base classes). So C's constructor runs before D is constructed (and C's destructor runs after D is destructed). The VMT of the object being constructed/destructed simply does not point at D's method table when C is being constructed/destructed, it points at C's method table instead.
How can change this behaviour (and get "D").
You cannot call a derived virtual method from inside of a base class constructor/destructor. The VMT does not contain a pointer to the derived class method table at those stages.
You have a quite fundamental problem here: You want to call a member function of a derived class on an object that does not exist yet.
Remember that objects are constructed by first constructing the base sub-object and then the derived object. So even if you'd manage to apply a “clever” trick to actually invoke the derived class' init function, as soon as that function would try to access any data member of the derived object, it would cause arbitrary damage. On the other hand, it is fine to access only the base object, as long as you don't rely on any invariant that the constructor has not established yet. Therefore, if you don't need access to the derived object's data, you can make the init function static and pass it a reference to the base class object.
Maybe this is coming close to what you are trying to do.
#include <iostream>
struct Base
{
Base(void (*fp)(Base&) = Base::init) { fp(*this); }
static void init(Base&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct Derived : Base
{
Derived() : Base(Derived::init) { }
static void init(Base&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int
main()
{
Base b {};
std::cout << std::endl;
Derived d {};
}
Output:
static void Base::init(Base&)
static void Derived::init(Base&)
Here, the base class constructor takes a function pointer to an initializer function that takes a reference to a Base object. The function defaults to Base::init but derived classes can replace it. Be aware, however, that in this design, the Base class constructor may not safely assume that any side effect of Base::init actually took place. It is fine as an extension mechanism (if Base::init does nothing or is disposable), though.
But I doubt that you need to use this kind of machinery. If all you want to do – and this should be the normal case – is to first initialize the base object and then the derived object, C++ already will do the right thing by default if you simply call the functions from the respective constructors.
struct Base
{
Base() { this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct Derived : Base
{
Derived() { this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
// main() as above ...
Output:
void Base::init()
void Base::init()
void Derived::init()
And if we only want to call the most derived class' init function, we can simply tell the base class not to run its own.
struct Base
{
Base(const bool initialize = true) { if (initialize) this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
struct Derived : Base
{
Derived() : Base(false) { this->init(); }
void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
// main() as above ...
Output:
void Base::init()
void Derived::init()
You only can remove init() from C constructor to not print "C".
To also print "D" add init() in D() constructor.
If for some cases you want print "C" or "D" and in some don't do something like this
struct C {
C() { };
void init() { cout << "C" << endl; };
};
struct D : public C {
D() : C()
{
if(some condition)
C::init();
if(some condition)
init();
};
void init() { cout << "D" << endl; }
};
D();
Having Class B that extends class A and overrides its functions can we be sure that when sending instance of (B*) as if it were type (A*) our overrides we created in class B will be called?
As long as the method on A is defined as virtual this will be the case for both pointers and references. For example
class A {
virtual void Method() {
cout << "A::Method" << endl;
}
};
class B {
// "virtual" is optional on the derived method although some
// developers add it for clarity
virtual void Method() {
cout << "B::Method" << endl;
}
};
void Example1(A* param) {
param->Method();
}
void Example2(A& param) {
param.Method();
}
void main() {
B b;
Example1(&b); // Prints B::Method
Example2(b); // Prints B::Method
}
Yes, if the functions are declared virtual - see http://www.parashift.com/c++-faq-lite/virtual-functions.html
Only if the function in A is declared virtual. When declared virtual, any overriden child functions are called even when cast as a parent class.