How does binding work for layered inheritance in C++? - c++

Say I have a virtual class:
class Tester {
virtual void Validate();
}
class Test1 : Tester {
void Validate(...) {
/implementation
}
}
class Test2 : Test1 {
void Validate(...) {
/implementation
}
}
To my understanding, the virtual should make it dynamic binding. But I'm uncertain what would happen if we have layered classes (ie. Test2 inheriting Test1 inheriting Tester):
void RunTest(Tester test) {
test.Validate(...);
}
...
Test2 test_candidate = Test2();
RunTest(test_candidate)
Which Validate method would this call?

void RunTest(Tester test)
This parameter of the function is an object of type Tester. It isn't a Test1 nor is it a Test2, hence the call cannot be to anything other than Tester::Validate.
When you pass Test2 as an argument, it will be converted to Tester by copying the base sub object.
Virtual dispatch requires indirection. You must call the function through a reference or a pointer, because only a reference or a pointer can point to a base subobject of a derived object.

Answer to your question
(see below or here why your example code does not behave like this)
Behaviour of "late" binding
Late binding always invokes the most specialized virtual function of the instance-type. In your case, all classes, Tester, Test1 and Test2 would invoke their own Validate(), as Test and Test2 override this function in each subclass.
However, if you would have
Test3 : public Test1 { /* Not overriding Validate() */ }
calling Validate() on an instance of Test3 would call Test1::Validate(), as that is the most specialized virtual implementation (it overrides Tester::Validate()).
Problem in your example code
In your example code, the function RunTest(Tester) passes the argument by value. If you pass an argument of type Test1, it makes a temporary copy of type Tester, as indicated by other answers, and if your compiler allows it at all without warning. This temporary copy is used in RunTest(Tester) and will always call Tester::Validate(), and that might not be the implementation of the object you passed as an argument to RunTest(Tester).
To use late binding, you should pass a reference or a pointer:
RunTest(Tester *t) { t->Validate(); }
or
RunTest(Tester &t) { t->Validate(); }
Using one of these will ensure that the behaviour is as described above (your answer).

There are quite a few issues with the code you provided:
1. Private Inheritance + Private Function Definitions
You need to declare your methods as public to be able to call them from an external function like RunTest. Also you probably want to inherit publicly in this case, so you can cast your Test2 class back to a Tester.
e.g.:
class Tester {
public:
virtual void Validate();
};
class Test1 : public Tester {
public:
void Validate();
};
class Test2 : public Test1 {
public:
void Validate();
};
2. A few recommendations
If you want to override a virtual method in a child class, you can use override to mark your function as such. That way you'll get a compile-time error in case the function couldn't be overriden (e.g. because of mismatched arguments)
(I'm assuming you meant void Validate() {} instead of void Validate(...))
Also if your classes contain any virtual methods, it's always a good idea to also provide a virtual destructor. (to properly clean up all the members in case it gets deleted by a pointer to its baseclass)
e.g.:
class Tester {
public:
virtual void Validate() {
// TODO
}
virtual ~Tester() = default;
};
class Test1 : public Tester {
public:
void Validate() override {
// TODO
}
};
class Test2 : public Test1 {
public:
void Validate() override {
// TODO
}
};
3. The RunTest() function will slice the Test2 object
You're passing a Tester instance to RunTest() by value.
This will result in the object being sliced, i.e. you'll loose everything stored in the derived objects.
void RunTest(Tester test);
// this
Test2 t2;
RunTest(t2);
// is equivalent to:
Test2 t2;
Test t = t2;
RunTest(t);
so essentially you're calling the RunTest() method with just a Test object, not Test2.
you can fix this by either bassing by reference or by pointer:
void RunTest(Tester& test) {}
// or
void RunTest(Tester* test) {}
Working Example
#include <iostream>
class Tester {
public:
virtual void Validate() {
std::cout << "Tester Validate" << std::endl;
}
virtual ~Tester() = default;
};
class Test1 : public Tester {
public:
void Validate() override {
std::cout << "Test1 Validate" << std::endl;
Tester::Validate();
}
};
class Test2 : public Test1 {
public:
void Validate() override {
std::cout << "Test2 Validate" << std::endl;
Test1::Validate();
}
};
void RunTest(Tester& test) {
test.Validate();
}
int main() {
Test2 t;
RunTest(t);
}
test it on godbolt!

Related

Override virtual method with static method

Is there any specific reason why I cannot override virtual method from base class with static one?
Anyone knows why it would be bad idea?
Example:
#include <cstdio>
class Foo
{
public:
virtual void SomeMethod() = 0;
};
class Bar : public Foo
{
public:
static void SomeMethod() override
{
printf("SomeMethod");
}
};
void SomeFunctionWithFoo( Foo *p )
{
p->SomeMethod();
}
int main()
{
Bar o;
o.SomeMethod();
SomeFunctionWithFoo( &o );
Bar::SomeMethod();
o.StaticSomeMethod();
}
Instead I have to do this:
#include <cstdio>
class Foo
{
public:
virtual void SomeMethod() = 0;
};
class Bar : public Foo
{
public:
void SomeMethod() override
{
StaticSomeMethod();
}
static void StaticSomeMethod()
{
printf("SomeMethod");
}
};
void SomeFunctionWithFoo( Foo *p )
{
p->SomeMethod();
}
int main()
{
Bar o;
o.SomeMethod();
SomeFunctionWithFoo( &o );
Bar::StaticSomeMethod();
o.StaticSomeMethod();
}
I think as long as you don't need to access member variables, your function can be static, so that it can serve behaviour without object. In the same time such static function can serve behaviour when using interface. But maybe I am wrong and I am missing something?
With one method and two classes, it is not problem, but I have case of 10 such methods inside class, and many classes that inherit.
In real world scenario, such possibility would make my code simpler.
Summary: member functions have an invisible first parameter that your static method doesn't have.
Details: Member functions (effectively) are effectively all static methods that have an "invisible" first parameter, which is the Bar* this parameter, which tells the method which instance of the class to use. So the signature of virtual void SomeMethod() is, under the covers, actually static void SomeMethod(Foo*), but static StaticSomeMethod() doesn't have the same number of parameters.
C++ is mostly able to pretend this parameter doesn't exist, but overrides are one case where it pops up. You also see it occur when trying to bind a member function to a std::function, where you have to explicitly pass the this as the first pointer.

How to access data of mother class from child class?

How can I access data of the mother class from a child class without creating an instace?
I've got something like:
#include <iostream>
class mother {
private:
public:
mother(){}
virtual ~mother(){}
virtual void func() const {std::cout << "mother " << dat <<std::endl;}
virtual void dat_set(std::string arg){dat=arg;}
std::string dat;
};
class child:mother {
public:
child(){}
~child(){}
void dat_set(std::string const arg) override { mother::dat_set(arg); }
void func() const override { std::cout << "child " << mother::dat << std::endl; }
};
int main (void) {
auto tmp = new mother();
tmp->dat_set("test");
auto foo = new child();
foo->func();
}
How do I make sure that func() invoked by foo gets access to the data stored in mother?
EDIT
Should I not be able to make std::string dat a static std::string dat? I tried that but I get compiler errors along the lines of
/tmp/ccZV7Y4n.o: In function `child::func()':
main.cpp:(.text._ZN5child4funcEv[_ZN5child4funcEv]+0x1d): undefined reference to `mother::dat[abi:cxx11]'
The trick to accessing functions inside base classes from derived classes is to redeclare them using virtual and override specifiers...
First, make the destructor virtual... (Since your compiler doesn't want virtual functions inside a class without a virtual destructor)
virtual ~mother() = default; // If the compiler is happy, we all are happy...
And then make your functions virtual...
virtual void dat_set(std::string const arg) { dat = arg; }
virtual void func() const { std::cout << "mother " << dat << std::endl; }
You have to define it again inside the child class since the child cannot become the mother, and that is the reason you cannot access those functions...
void dat_set(std::string const arg) override { mother::dat_set(arg); }
void func() const override { mother::func(); }
Here you have to have the exact same declaration you had in the base class (except virtual which is redundant when override is used...) and add override specifier that re-declares the same function you had in the base class inside the child class...
For behavior just put mother::func() (mother::dat_set(/*params go here*/) for calling the function with parameters, and I bet you might already know that) to call the respective function...
Note: The override specifier (since C++11) is similar to the virtual specifier, except that it is only usable in dervied classes/structures, and makes the usage of virtual inside child declarations optional (In your base class you have to use virtual instead)...
Edit: You can assign a derived class to a base class but it is not possible to do the opposite, and that is the reason why your code fails... A close attempt to doing something like this would be the usage of namespaces, for example:
namespace some_namespace
{
static std::string dat;
// The child and mother class declarations and other things go here...
}
Kind regards,
Ruks.

const-correctness in void methods and lambda 'trick'

I have a method that accepts a reference of an object as const, this method doesn't change anything of the method and the const indicates that, the thing is that this method also calls other method that is within the class and is void, doesn't accept any argument and is also virtual, meaning that the class that extends the base class can override the method BUT it needs to be const as well. Eg:
#include <iostream>
class Boz
{
public:
virtual void introduce() const = 0;
};
class Foo
{
public:
virtual void callable() const
{
// ...
}
void caller(const Boz& object) const
{
callable();
object.introduce();
}
};
class Bar : public Boz
{
public:
void introduce() const
{
std::cout << "Hi." << std::endl;
}
};
class Biz : public Foo
{
public:
void callable() const
{
std::cout << "I'm being called before the introduce." << std::endl;
}
};
int main(void)
{
Biz biz;
biz.caller(Bar());
return 0;
}
The output would be:
I'm being called before the introduce.
Hi.
As you can see callable must to be const in order to be called. If I change and do this:
class Biz : public Foo
{
public:
void callable()
{
std::cout << "I'm being called before the introduce." << std::endl;
}
};
It will compile not errors are thrown but the callable method won't be called, but the virtual one as it's defined as const. It's quite obvious.
The trickiest part here:
class Foo
{
public:
virtual void callable()
{
// ...
}
void caller(const Boz& object) const
{
auto trick = [&] () { callable(); };
trick();
object.introduce();
}
};
class Biz : public Foo
{
public:
void callable()
{
std::cout << "I'm being called before the introduce." << std::endl;
}
};
It works and the callable method is called. No errors like passing 'const ...' as 'this' argument.
What I'm trying to do is to call callable without the need of being const and the reason is simple: The method doesn't change anything, he don't have access to the object that is begin passed as argument on caller method then we assume that he doesn't have the need to be const but the compiler throws an error even that way. The real problem is that callable is virtual and classes can extend the base class, implement their own callable and try to call other methods but can't if it's not const as well.
What I want is pretty much that, is to know how can I call the virtual method without the need of being const (the reason is pretty much that, I'm kind forcing the users that extends the class and override the callable method to only call const methods and this is not what I want) and of course understand what happens with the lambda and why it works.
That code with the lambda definitely shouldn't compile, it's simply a GCC bug (reported as PR 60463 and PR 60755) which is now fixed in the svn trunk, by http://gcc.gnu.org/r210292
If you really need to call a non-const member function from a const one you need to cast away the constness:
const_cast<Foo*>(this)->callable();
But this is quite risky, for at least two reasons
if the object was declared const then it is undefined behaviour e.g. const Foo f; f.caller(boz); is undefined behaviour.
you're calling a virtual function, you don't necessarily know that the derived class' override definitely doesn't modify anything. The whole point of virtual functions is that a derived class can do something different and the base class doesn't know the details.
I would change your design so that the virtual function you want to call is const, or the caller function is non-const. Anything else is dangerous.

C++ new operator with valid vtable without calling constructor

Is it possible to create an instance of a class on a heap without calling default constructor and with a valid vtable for inheritance? Let me demonstrate what I will like to do:
class A
{
protected: virtual void _fake_static_method()
{
}
};
class B1 : public A
{
protected: virtual void _fake_static_method()
{
std::cout << "Hello";
}
public: static void run_fake_static_method()
{
B1* dummy = static_cast<B1*>(::operator new(sizeof(B1)));
dummy->_fake_static_method();
free(dummy);
}
}
class B2 : public A
{
public: static void run_fake_static_method()
{
B2* dummy = static_cast<B2*>(::operator new(sizeof(B2)));
dummy->_fake_static_method();
free(dummy);
}
}
Here I want to call a static method from example B1::run_fake_static_method(). In that method I want to run a member method, but I don't want to call the default constructor. I need such an implementation to remove the virtual method without a compiling error among other errors. Like a "virtual static method" I hope you understand what I want to do.
Is there a special trick that I can get this to work? :)

c++ overriding a function only for a specific instance

I was wondering whether there's a way to override a function for a specific instance only. For ex,
class A
{
public:
...
void update();
...
}
int main()
{
...
A *first_instance = new A();
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A *second_instance = new A();
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A *third_instance = new A();
// ....so on.
...
}
Is there a way to achieve this?
I think virtual function is just what you want, with virtual function, different instances of the same type can have different functions, but you need to inherit the base class. for example
class A
{
public:
...
virtual void update()
{
std::cout << "Class A\n";
}
...
};
class B: public A
{
public:
virtual void update()
{
std::cout << "Class B\n";
}
};
class C: public A
{
public:
virtual void update()
{
std::cout << "Class C\n";
}
};
int main()
{
...
A *first_instance = new A();
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A *second_instance = new B();
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A *third_instance = new C();
// ....so on.
...
}
each instance in the above code will bind different update functions.
Besides, you can also use function pointer to implement your requirement, but it is not recommended. For example
class A
{
public:
A(void(*u)())
{
this->update = u;
}
...
void (*update)();
};
void a_update()
{
std::cout << "update A\n";
}
void b_update()
{
std::cout << "update B\n";
}
void c_update()
{
std::cout << "update C\n";
}
int main()
{
...
A first_instance(a_update);
// I want this to have a specific update() function.
// ex. void update() { functionA(); functionB(); ... }
A second_instance(b_update);
// I want this to have a different update() function than the above one.
// ex. void update() { functionZ(); functionY(); ...}
A third_instance(c_update);
// ....so on.
...
}
Hope helps!
Hold a function in the class.
#include <iostream>
#include <functional>
using namespace std;
class Foo
{
public:
Foo(const function<void ()>& f) : func(f)
{
}
void callFunc()
{
func();
}
private:
function<void ()> func;
};
void printFoo() { cout<<"foo"<<endl; }
void printBar() { cout<<"bar"<<endl; }
int main()
{
Foo a(printFoo);
Foo b(printBar);
a.callFunc();
b.callFunc();
}
You may have noticed that the end brace of a class is often followed by a semicolon, whereas the end braces of functions, while loops etc don't. There's a reason for this, which relates to a feature of struct in C. Because a class is almost identical to a struct, this feature exists for C++ classes too.
Basically, a struct in C may declare a named instance instead of (or as well as) a named "type" (scare quotes because a struct type in C isn't a valid type name in itself). A C++ class can therefore do the same thing, though AFAIK there may be severe limitations on what else that class can do.
I'm not in a position to check at the moment, and it's certainly not something I remember using, but that may mean you can declare a named class instance inheriting from a base class without giving it a class name. There will still be a derived type, but it will be anonymous.
If valid at all, it should look something like...
class : public baseclass // note - no derived class name
{
public:
virtual funcname ()
{
...
}
} instancename;
Personally, even if this is valid, I'd avoid using it for a number of reasons. For example, the lack of a class name means that it's not possible to define member functions separately. That means that the whole class declaration and definition must go where you want the instance declared - a lot of clutter to drop in the middle of a function, or even in a list of global variables.
With no class name, there's presumably no way to declare a constructor or destructor. And if you have non-default constructors from the base class, AFAIK there's no way to specify constructor parameters with this.
And as I said, I haven't checked this - that syntax may well be illegal as well as ugly.
Some more practical approaches to varying behaviour per-instance include...
Using dependency injection - e.g. providing a function pointer or class instance (or lambda) for some part of the behavior as a constructor parameter.
Using a template class - effectively compile-time dependency injection, with the dependency provided as a function parameter to the template.
I think it will be the best if you'll tell us why do you need to override a function for a specific instance.
But here's another approach: Strategy pattern.
Your class need a member that represent some behaviour. So you're creating some abstract class that will be an interface for different behaviours, then you'll implement different behaviours in subclasses of that abstract class. So you can choose those behaviours for any object at any time.
class A;//forward declaration
class Updater
{
public:
virtual ~Updater() {};//don't forget about virtual destructor, though it's not needed in this case of class containing only one function
virtual void update(A&) = 0;
}
class SomeUpdater
{
public:
virtual void update(A & a);//concrete realisation of an update() method
}
class A
{
private:
Updater mUpdater;
public:
explicit A(Updater updater);//constructor takes an updater, let's pretend we want to choose a behaviour once for a lifetime of an object - at creation
void update()
{
mUpdater.update(this);
}
}
You can use local classes, yet, personally, I consider the "hold function in the class" approach mentioned in the other answer better. I'd recommend the following approach only if doFunc must access internals of your base class, which is not possible from a function held in a member variable:
class ABase {
public:
void Func () { this->doFunc (); }
private:
virtual void doFunc () = 0;
public:
virtual ~ABase () { }
};
ABase* makeFirstA () {
class MyA : public ABase {
virtual void doFunc () { std::cout << "First A"; }
};
return new MyA;
}
ABase* makeSecondA () {
class MyA : public ABase {
virtual void doFunc () { std::cout << "Second A"; }
};
return new MyA;
}
int main () {
std::shared_ptr<ABase> first (makeFirstA ());
std::shared_ptr<ABase> second (makeSecondA ());
first->Func ();
second->Func ();
}
From a design patterns point of view, the "local classes" approach implements the template method pattern, while the "hold a function(al) in a member variable" approach reflects the strategy pattern. Which one is more appropriate depends on what you need to achieve.