Let's say I have a base class and a derived class:
struct A
{
void foo()
{
std::cout << "Do one thing." << std::endl;
}
};
struct B: public A
{
void foo()
{
std::cout << "Do another thing." << std::endl;
}
};
B myB;
myB.foo();
Normally this would print Do another thing., but what if I wanted foo() to also run the base foo() and print:
Do one thing.
Do another thing.
Call A::foo() in B::foo(), that way the base class's function will execute first, then the rest of the derived class function executes after that.
struct A
{
void foo()
{
std::cout << "Do one thing." << std::endl;
}
};
struct B : public A
{
void foo()
{
A::foo();
std::cout << "Do another thing." << std::endl;
}
};
Related
This is purely a theoretical question. I don't have a particular use case in mind.
Can the virtuality of a C++ function be suppressed somewhere down the class hierarchy, or is it that once a virtual function is defined in a base class, it remains virtual down the rest of its class hierarchy?
I wrote some sample code where I was attempting to suppress the virtuality of a method defined up the class hierarchy but I did not succeed. My sample code follows:
class Base {
public:
virtual void myFunc() {
std::cout << "myFunc in Base" << std::endl;
}
};
class Child : public Base {
public:
void myFunc() {
std::cout << "myFunc in Child" << std::endl;
}
};
class GrandChild : public Child {
public:
void myFunc() {
std::cout << "myFunc in GrandChild" << std::endl;
}
};
int main() {
Base* ptr = new GrandChild();
ptr->myFunc();
return 0;
}
The output is as follows:
myFunc in GrandChild
One thing you can do is create a member with a different signature (even using defaulted arguments).
That is:
struct Base
{
virtual void foo()
{
std::cout << "Base::foo" << std::endl;
}
};
struct Derived : Base
{
void foo(int = 0)
{
std::cout << "Derived::foo" << std::endl;
}
};
...
Base * ptr = new Derived;
ptr->foo(); // will invoke Base::foo()
I need to call the base method A::foo() from derived class by pointer.
#include <iostream>
struct A{
virtual void foo() { std::cout << "A::foo()" << std::endl; }
};
struct B:A{
virtual void foo() { std::cout << "B::foo()" << std::endl; }
void callBase(void (A::*f)()){
(this->*f)();
}
};
int main(){
B* p=new B();
p->callBase(&A::foo);
}
This code output "B::foo". Is it possible to call A::foo() by pointer to method?
Well, you can do something similar using some tricks with overwriting the value of this. You probably should never try to do that though, vtable pointers aren't meant to be modified by hand.
To do what you described, we need to have the pointer to A's vtable. Our object p has only pointer to B's vtable, so we need to store second pointer in a field within A's constructor.
Here is the code:
#include <iostream>
struct A{
virtual void foo() { std::cout << "A::foo()" << std::endl; }
int *a_vtable_ptr;
// First, save value of A's vtable pointer in a separate variable.
A() { a_vtable_ptr = *(int**)this; }
};
struct B:A{
virtual void foo() { std::cout << "B::foo()" << std::endl; }
void callBase(void (A::*f)()){
int *my_vtable_ptr = *(int**)this;
// Then modify vtable pointer of given object to one that corresponds to class A.
*(int**)this = a_vtable_ptr;
(this->*f)(); // Call the method as usual.
// Restore the original vtable pointer.
*(int**)this = my_vtable_ptr;
}
};
// Function main() is not modified.
int main(){
B* p=new B();
void (A::*f)() = &A::foo;
p->callBase(f);
}
Output:
A::foo()
Process finished with exit code 0
Virtual methods are designed to implement polymorphism and pointers to virtual methods supports their polymorphic behavior. But you given the possibility to call the base method by explicitly calling p->A::foo().
So if you want to call base method by pointer, you should make it non-virtual (as #PasserBy mentioned in comments).
Code example:
struct A {
virtual void foo() { std::cout << "A::foo()" << std::endl; }
void bar() { std::cout << "A::bar()" << std::endl; }
void callBase(void (A::*f)()) { (this->*f)(); }
};
struct B : A {
virtual void foo() { std::cout << "B::foo()" << std::endl; }
void bar() { std::cout << "B::bar()" << std::endl; }
};
int main()
{
A* p = new B();
p->foo();
p->bar();
p->callBase(&A::foo);
p->callBase(&A::bar);
p->A::foo();
p->A::bar();
}
Output:
B::foo()
A::bar()
B::foo()
A::bar()
A::foo()
A::bar()
Output of this program is "Method B". How can an instance of the parent object call the child class's function through a static_cast?
To make things more confusing, if I make method() virtual, then this code outputs "Method A".
Can anyone explain what is happening here?
class A {
public:
void method() {
cout << "Method A" << endl;
}
};
class B : public A {
public:
void method() {
cout << "Method B" << endl;
}
};
int main() {
A a;
B* bptr = static_cast<B*>(&a);
bptr->method();
}
I'm reading topics related to object destruction in the book Inside C++ Object Model and encounter this problem.
It says that before the execution of user-defined destructor, the destructor will be augmented. The first step of the augmentation is reset the vptr pointer to the virtual function table of that class. I remember that correspondingly, just before the execution of user code (statements in the blocked constructor body) in the constructor, the vptr has already been properly set in case virtual member functions should be invoked during construction.
The problem is whether the reset vptr step in the destructor augmentation is a must.
If so, there must be some possibility that the vptr in an object be updated somewhere.
When may this happen?
It can happen in the destructor of a derived class. Say you have:
class Foo : public Bar : public Baz
Now, say you have a Foo. In Foo::~Foo, it's a Foo, and that's the virtual function table it must use. But when Foo::~Foo completes, it's not a Foo anymore. It's a Bar, and that's what virtual function table it must use. When Bar::~Bar completes, it's just a Baz, so in Baz::~Baz, it must use the virtual function table for Baz.
The pointer to the virtual function table does not change except when in constructors and destructors.
Here's some example code to play with:
#include <string>
#include <iostream>
class Foo
{
public:
Foo() { print("Foo::Foo"); }
virtual ~Foo() { print("Foo::~Foo"); }
virtual void print(std::string j) { std::cout << j << "(Foo)" << std::endl; }
};
class Bar : public Foo
{
public:
Bar() { print("Bar::Bar"); }
virtual ~Bar() { print("Bar::~Bar"); }
virtual void print(std::string j) { std::cout << j << "(Bar)" << std::endl; }
};
class Baz : public Bar
{
public:
Baz() { print("Baz:Baz"); }
virtual ~Baz() { print("Baz::~Baz"); }
virtual void print(std::string j) { std::cout << j << "(Baz)" << std::endl; }
};
int main(void)
{
std::cout << "Constructing Baz" << std::endl;
{
Baz j;
std::cout << "Baz constructed" << std::endl;
}
std::cout << "Baz destructed" << std::endl;
}
Output is:
Constructing Baz
Foo::Foo(Foo)
Bar::Bar(Bar)
Baz:Baz(Baz)
Baz constructed
Baz::~Baz(Baz)
Bar::~Bar(Bar)
Foo::~Foo(Foo)
Baz destructed
You can see how a Foo is constructed and then used to make a Bar which is used to make the final Baz. At destruction time, ~Baz turns it into a Bar and then ~Bar turns it into a Foo. ~Foo does the final destruction.
No, there's no such possibility. The vptr is only updated from constructor and from destructor.
The update from destructor is done for a very specific reason: to make sure that all virtual functions called from inside the destructor of class A will call virtual functions defined in A or higher in the hierarchy, but not functions from classes located lower in the hierarchy. Basically, this is the same (symmetrical) reason why vptr pointer is updated in each constructor as well.
For example, in this hierarchy
struct A {
virtual void foo() { std::cout << "A" << std::endl; }
~A() { foo(); }
};
struct B : A {
virtual void foo() { std::cout << "B" << std::endl; }
~B() { foo(); }
};
struct C : B {
virtual void foo() { std::cout << "C" << std::endl; }
~C() { foo(); }
};
C c;
Each destructor in the destructor chain for the object c will perform a call to virtual function foo. The destructor of C will call C::foo, the destructor of B will call B::foo (not C::foo) and the destructor of A will call A::foo (again, not C::foo). This happens that way specifically because each destructor explicitly sets the vptr pointer to the virtual table of its own class.
A more convoluted example of the same behavior might look as follows
struct A;
extern void (A::*fun)();
struct A {
virtual void foo() { std::cout << "A" << std::endl; }
~A() { (this->*fun)(); }
};
void (A::*fun)() = &A::foo;
struct B : A {
virtual void foo() { std::cout << "B" << std::endl; }
~B() { (this->*fun)(); }
};
struct C : B {
virtual void foo() { std::cout << "C" << std::endl; }
~C() { (this->*fun)(); }
};
C c;
The difference is that this example is more likely to physically use the vptr and the virtual method table to resolve the calls. The previous example is usually optimized by the compiler into direct non-virtual calls to proper foo.
Firstly, let me apologise for the title, I honestly couldn't think how to word it better.
The example below should make my question a little clearer:
class Foo {
public:
Foo(int x);
};
class Bar : public Foo
{
public:
Bar(int y) : Foo(y);
};
Demonstrates code that would force the Bar constructor to call the Foo constructor with parameter Y. My question is, is there a similar method for inheriting a derived class function to call a base class function?
For example all calls to Bar.Func(); would also automatically call Foo.Func();?
class Foo {
public:
Foo(int x);
void DoIt();
};
class Bar : public Foo
{
public:
Bar(int y) : Foo(y);
void DoIt();
};
void Bar::DoIt()
{
Foo::DoIt();
}
If Foo is intended to be derived from and used polymorphicly, you should declare DoIt as virtual. In addition, you will also want a virtual base class destructor.
Automatically, no. You can use Base::member() to call it, though.
struct foo {
void frob() { std::cout << "foo::frob" << std::endl; }
};
struct bar : foo {
void frob() { foo::frob(); std::cout << "bar::frob" << std::endl; }
};
Any public function declared in Foo is also accessible via Bar (the same function will get called). If you may need to override the function in Bar to alter its behaviour, make it virtual.
This is the code you'll need if you want to 'inherit' the function statements for a function F() from its base. Declare F() virtual in Foo, implement some statements there. Then declare F() in Bar and make a call to Foo::F() at the beginning of the implementation of Bar::F():
class Foo {
public:
Foo(int i) { cout << "Foo(" << i << ") called." << endl; }
virtual void F() { cout << "foo::F() called." << endl; }
virtual ~Foo() {};
};
class Bar : public Foo {
public:
Bar(int i) : Foo(i) { cout << "Bar(" << i << ") called" << endl; }
void F() { Foo::F(); cout << "bar::F() called" << endl; }
};
int main(int argc, char** argv) {
Bar b(3);
b.F();
}
gives
Foo(3) called.
Bar(3) called
foo::F() called.
bar::F() called