Is there a way to make a pointer on member function in base class if it is a virtual function and it is overridden in derived class?
Consider the code as follows
#include <iostream>
#include <functional>
struct Base
{
virtual void g() const
{
std::cout << "Base" << std::endl;
}
};
struct Derived : Base
{
virtual void g() const override
{
std::cout << "Derived" << std::endl;
}
};
int main()
{
Derived d;
(d.*(&Base::g))();
std::mem_fn(&Base::g)(d);
return 0;
}
It prints ‘Derived’ twice despite I make a pointer on Base::g. Is there a way to keep function g virtual and overridden and get member function pointer that will print ‘Base’ for d?
Just call the base function
int main()
{
Derived d;
d.g();
Base* b = &d;
b->Base::g();
//or
d.Base::g();
//or
auto callLater = [&d]() { d.Base::g();};
callLater();
return 0;
}
Output
Derived
Base
Base
Base
This can be made a pointer to the function; but it needs be to the member function Base::g() of the object being pointed to.
You might define a non-virtual function real_g called from g so code
struct Base
{
void real_g() const {
std::cout << "Base" << std::endl;
}
virtual void g() const { real_g(); };
};
Then later in main
std::mem_fn(&Base::real_g)(d);
See wikipage on virtual method table, this C++ reference and the C++ standard n3337 or better. Read also a good C++ programming book and the documentation of your C++ compiler, e.g. GCC
See also this answer (explaining naively what are vtables, in simple cases)
Related
Assuming I have code like this:
struct Base1 {
virtual void foo() = 0;
};
struct Base2 {
virtual void foo() = 0;
};
struct Derived : Base1, Base2 {
void foo() override {}
};
I am trying to produce a single override for several functions of different base classes with same name/signature.
Is such an overriding legal and well-defined in c++?
Is such an overriding legal and well-defined in c++?
Yes, it is perfectly legal and well defined as long as you override the virtual function in the derived class.
If you create an object of Derived structure and invoke the foo function it will invoke the overridden function.
The compiler will always search the called function from local to the global scope. So here compiler will check if foo is defined in the Derived scope if not found it will check in the Base scope and since you have provided the definition of foo in the derived scope the compiler won't check Base scope.
Try this code and you will get a better idea.
The output will be This is derived.
#include <iostream>
using namespace std;
struct Base1 {
virtual void foo() {
cout << "This is base1" << endl;
}
};
struct Base2 {
virtual void foo() {
cout << "This is base2" << endl;
}
};
struct Derived : Base1, Base2 {
void foo() {
cout << "This is derived" << endl;
}
};
int main() {
Derived d;
d.foo();
return 0;
}
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();
If I have a Base and a Derived Class:
class Base {
//...
};
class Derived : public Base {
//...
};
Is it possible to overload functions in the following way?
void DoSomething(Base b) {
cout << "Do Something to Base" << endl;
}
void DoSomething(Derived d) {
cout << "Do Something to Derived" << endl;
}
What happens if I do this:
int main() {
Derived d = Derived();
DoSomething(d);
}
Derived is also a Base.. so which version gets called?
Yes, C++ lets you overload functions for base and derived classes. In fact, this mechanism is used by the standard library <algorithm> functions to select the correct algorithm depending on the types of the iterators passed in.
A Derived object is also a Base, but DoSomething(Derived) is an exact match, so it's preferred. DoSomething(d) will call DoSomething(Derived).
However, note that you can't get polymorphic behaviour this way. That is, if you have a Base& that actually refers to a Derived object, it still calls DoSomething(Base): that is, it dispatches on the static type. (In fact, since you are passing by value, it copies out only the Base part of the object into the parameter.) To get polymorphic behaviour, you would have to make DoSomething into a virtual member function (or make DoSomething(Base& b) call a virtual member function on b.)
The derived function will be called and used because it matches this "DoSomething(Derived d)"
signature.
Have you consider using the code like this instead:
#include<iostream>
using namespace std;
class Base {
public:
virtual void DoSomething();
};
class Derived : public Base {
public:
void DoSomething() override;
};
void Base:: DoSomething() {
cout << "Do Something to Base" << endl;
}
void Derived :: DoSomething() {
cout << "Do Something to Derived" << endl;
}
int main() {
Base *d = new Derived();
d->DoSomething();
delete d;
return 0;
}
It accomplished the same task, and allows you to take advantage of polymorphisms strength.
i do not understand why this behavior occurs:
class Base
{
public:
virtual void enablePolymorphism();
};
class Derived : public Base
{
public:
void enablePolymorphism();
};
class Derived2 : public Base
{
public:
void enablePolymorphism();
};
void callMe(Base base)
{
printf("base");
}
void callMe(Derived derived)
{
printf("derived");
}
void callMe(Derived2 derived2)
{
printf("derived2");
}
int main()
{
Base* pointer = new Derived();
Base* pointer2 = new Derived2();
callMe(*pointer);
callMe(*pointer2);
return 0;
}
this is what i actually want my code to do and i want the method callMe() to be outside the classes therefore i cannot use virtual functions, i want at run-time for the program to call callMe(Derived derived) when i do callMe(*pointer) and callMe(Derived2 derived2) when i do callMe(*pointer2) for which the output would be derivedderived2 but that's not what happens, at compile-time pointer and pointer2 are assumed to be of Base class when dereferenced so the callMe(Base base) is called instead and the output is basebase. How do i achieve the output i want? thank you.
void callMe(A);
void callMe(B);
A*ptr;
callMe(*ptr); // guess which of the above is called?
this has nothing to do with polymorphism, but is simple overloading resolution.
Runtime polymorphism applies only to member functions that are marked with the virtual keyword (or that override a virtual member function):
virtual void callMe();
For a non-member function, or a non-virtual member function, the appropriate overload is selected at compile time based on the declared type (not the runtime type) of the argument(s).
The only thing the compiler sees is that the expression *pointer is of type Base& and therefore succeeds into choosing the correct overload callMe(Base) for the function.
In your case, you can use a polymorphic function instead:
#include <memory>
#include <iostream>
class Base {
public:
virtual void callMe() { std::cout << "called base"; }
};
class Derived : public Base {
public:
virtual void callMe() { std::cout << "called derived"; }
};
int main() {
std::unique_ptr<Base> pointer(new Derived());
pointer->callMe();
return 0;
}
And here is the live example.
What's the difference between redefining and using a virtual function? Don't they serve the same purpose? You are allowing objects of a derived class to call their own versions of a function by the same name in both cases..so where is the distinction?
An example says it best:
#include <iostream>
using namespace std;
class A {
public:
virtual void f1() { cout << "Class A" << endl; }
void f2() { cout << "Class A" << endl; }
virtual ~A(){}
};
class B : public A {
public:
virtual void f1() { cout << "Class B" << endl; }
void f2() { cout << "Class B" << endl; }
virtual ~B(){}
};
int main()
{
A *a = new B;
a->f1();
a->f2();
}
...
$ ./override
Class B
Class A
You can see that when we reference the instance of B, f1() still calls B's version, but f2() calls A's.
When you declare a function virtual, you are saying that when we call it we should use the vtable to look up the right version of the function to call, and so you will always get the most derived version of the function, even if you reference it as an ancestor type. Without virtual, it will simply use the definition in the type you are referencing it as.
The distinction is when you have a reference or pointer to the base class. A call to a virtual function will call the most-derived version while a call to a normal function will call the base-class version.
If you're using a variable directly or a reference or pointer to the most-derived class, there is no practical difference.
TL;DR
The only way to take advantage of the polymorphism in C++ is via virtual functions and pointers (and references). The virtual keyword will tell the compiler to allocate a virtual function table where to look when deciding what version of the virtual function to call when dealing with pointer to the base class with a dynamic type that is of a child class.
How does polymorphism work in C++
Let's take a simple example:
class A { public: virtual void eat() { std::cout << "Class A" << std::endl; }
class B : public A {};
class C : public B { virtual void eat() { std::cout << "Class C" << std::endl; }
Note: the virtual keyword could be omitted after the first function/method definition.
The following:
A a; B b; C c;
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
ptrA->eat();
ptrB->eat();
ptrC->eat();
will print:
Class A
Class A
Class C
If we wouldn't have declared the function eat virtual, the output would have simply been:
Class A
Class A
Class A
But why
A* ptrA = &a; A* ptrB = &b; A* ptrC = &c;
Instead of
A* ptrA = &a; B* ptrB = &b; C* ptrC = &c;
With the second version, the eat() method can simply be redefined for each derived class, without the need for virtual, right?