I come from a Python background, and currently I'm learning OOP in C++.
I'm having problems figuring out how to get the code to call the correct method in a helper class HelperBase that is inherited to HelperChild.
#include <iostream>
class HelperBase {
public:
HelperBase() {}
virtual void something() {
std::cout << "HelperBase" << std::endl;
}
};
class HelperChild : public HelperBase {
public:
HelperChild() {}
void something() {
std::cout << "HelperChild" << std::endl;
}
};
The HelperBase class i used in the class Base, where it is set as a member variable.
class Base {
public:
Base(HelperBase &helperBase) : hb(helperBase) {}
virtual void print() {
std::cout << "-- Base" << std::endl;
hb.something();
}
HelperBase hb;
};
Then this class is used as the base class of the class Child:
class Child : public Base {
public:
Child(HelperChild &helperChild) : Base(helperChild) {
helperChild.something();
}
};
The main method is
int main() {
HelperChild helperChild;
Child child(helperChild);
child.print();
return 0;
}
This outputs the following:
HelperChild
-- Base
HelperBase
Why isn't the 'HelperChild' printed in the last line? What changes do I have to do to achieve this? (I'm not sure if I have used virtual in the correct way).
EDIT: In the actual case im trying to figure out, Base::print is a really large method that I don't want to override in the Child class. I just want to change the behaviour of the helper class.
Copy constructor will NOT copy derived object, it will get sliced and create a base object.
To elaborate, you may consider copy constructor as "copy by value", every value of derived object would be copied to create a base object. Since your Helper classes have no class members, it copied nothing.
Also function is not copyable, C++ handles virtual functions by vtable. A base class would have a vtable of base class, that's why hb.something() called the base version.
Last line is printing Helper base because your Base has a HelperBase but not a derived HelperChild.
class Base {
public:
Base(HelperBase &helperBase) : hb(helperBase) {} // hp(helperBase) means you still have a helper base.
virtual void print() {
std::cout << "-- Base" << std::endl;
hb.something();
}
HelperBase hb;
};
Then in main, child.print() will call the hb.something() which belongs to HelperBase.
To achieve polymorphism, you need a pointer to take the instance of HelperChild. It's called Dependency Injection and I assumed you were trying to achieve it.
class Base {
public:
Base(HelperBase &helperBase) {
hb = &helperBase;
}
virtual void print() {
std::cout << "-- Base" << std::endl;
hb->something();
}
HelperBase* hb;
};
The HelperBase hb in class Base is always of type HelperBase - even if you call print from an instance of type Child.
There are various ways to achieve what you want. One option is to use PIMPL to store a pointer to a Helper class. A different option is to use CRTP.
Related
Is there some way that I can make sure that the base classes function is called from the overridden function in the child class.
Example:
#include <iostream>
class Base
{
public:
virtual void func()
{
std::cout << "Really important code was ran" << std::endl;
}
};
class ChildExplicit : public Base
{
void func() override
{
Base::func();
std::cout << "child class explicitly calling Base::func" << std::endl;
}
};
class ChildImplicit : public Base
{
void func() override
{
std::cout << "child not explicitly calling Base::func" << std::endl;
}
};
int main()
{
Base* explicitChild = new ChildExplicit();
Base* implicitChild = new ChildImplicit();
explicitChild->func();
std::cout << std::endl;
implicitChild->func();
}
This should either output this:
Really important code was ran
child class explicitly calling Base::func
Really important code was ran
child not explicitly calling Base::func
or yield some kind of error that Base::func was not called in ChildImplicit::func.
One solution that would be possible is to make func non virtual and creating a second protected function that will be called in Base::func, the child classes would then override the protected function. But as you can imagine if apply this to a Base class of the Base class of the Base class scenario and each of there implementations must be called this gets quite messy. Would there be an other way to achieve the same goal?
How to call the member function of child inside the member function of parent class
This needs to accomplished as a part of gtest and gmock.
Example:
class Base
{
public:
void my_read()
{
cout << "Base read\n";
}
void my_write()
{
cout << "Base write\n";
my_read();
}
};
class Derived: public Base
{
public:
void my_read()
{
cout << "Derived read\n";
}
};
int main()
{
Derived d;
d.my_write();
return 0;
}
The desired output is:
Base write
Derived read
The actual output is:
Base write
Base read
As this is the situation of writing the test case, I cant change the code implementaion.
Considering Derived class as a Mock class from the Base, I have specific implementation for my_read().
How to use this implementation in child without passing any other instances.
Just one solution's seen by me yet, declaring the my_read() with virtual (which modifies the base a bit):
virtual void my_read()
{
std::cout << "Base read\n";
}
Solves your problem. The output was:
Base write
Derived read
I understand that C++ implements runtime polymorphism thorugh virtual functions and that virtual keyword is inherited but I don't see use of virtual keyword in derived class.
e.g. In below case even if you dropped virtual keyword in derived class still ptr->method() call goes to derived::method. So what extra this virtual keyword is doing in derived class?
#include<iostream>
using namespace std;
class base
{
public:
virtual void method()
{
std::cout << std::endl << "BASE" << std::endl;
}
};
class derived: public base
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED" << std::endl;
}
};
int main()
{
base* ptr = new derived();
ptr->method();
return 9;
}
If the method of the derived class matches a virtual method of one of the base classes by name and signature, and the matched method is virtual, then the method of a derived class becomes virtual as well. So, technically, there is no need to mark such methods as «virtual» in derived classes. However, before C++11 it used to be a good practice just because it is a great hint to those reading the code (it could be hard to keep in mind all of the virtual functions of base class(es)).
Starting with C++11, there are two additional keywords for doing this in the derived classes that help both readability and code robustness. They are «override» and «final». For example, putting «override» in a derived class`s method ensures that a corresponding method of a base class is, in fact, virtual. The «final» keyword does the same plus it prevents the method from being further overriden.
I also wrote about this with more real-world rationales and code examples in my blog, here.
Hope it helps. Good Luck!
Nothing. Just to help remind you what functions are virtual or not.
virtual is only necessary in the base class declaration. It's optional in the derived class(es), and probably serves mostly as a reminder in those cases.
C++11 introduces override to make things even more explicit : it explicitely marks a method in a derived class as being an override of a virtual method of a base class.
Implicitly virtual methods in derived classes are virtual in derived classes, no need to explicitly define them virtual.If you declare it will be redundant declaration.
ptr->method();
When the compiler came across the above statement
-> It will try to resolve the above statement, as the method() function is virtual, compiler postpone the resolving of that call to run time.
->As you created the object of derived class at run time, now the compiler will get to know that this method is of derived class.
what extra this virtual keyword is doing in derived class?
Consider this scenario there is one more derived class called Derived2 inherting form derived and it has its own virtual method.
class derived2: public derived
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED2" << std::endl;
}
};
If you call the method() in main like below
int main()
{
base* ptr = new derived2();
ptr->method(); //derived2 class method() will get called
return 9;
}
If the method() in derived2 is not virtual by default, you will end up calling teh derived version of method(), loosing the benefit of runtime polymorphism.
Hence the authors of c++ did a wonderful job here, by making the virtual key word inheritance hierarchical.
virtual keyword is optional in drive class because according to the rule when you drive a class with the base class which have virtual function and when you override the virtual function in drive class compiler implicitly assign virtual keyword along with the function. So you not need to explicitly assign the virtual keyword. But this keyword is necessary during multilevel inheritance.
Example:
In your code we add this code.
class derived: public base {
public:
virtual void method() { // In this line virtual keyword is optional.
std::cout << std::endl << "DERIVED :: method function" << std::endl;
}
virtual void display() {
std::cout << std::endl << "DERIVED :: display function" << std::endl;
}
};
class deriveChild: public derived {
public:
void method() {
std::cout << std::endl << "DERIVECHILD :: method" << std::endl;
}
void display() {
std::cout << std::endl << "DERIVECHILD:: display" << std::endl;
}
};
In the main() if you use below code it will give you different output.
base *ptr = new deriveChild();
ptr->method(); // will compile and execute
ptr->display(); // will generate error because display() is not part of base class.
Now if you want to use display() of deriveChild class then use this code.
derived *ptr = new deriveChild();
ptr->method(); // Compile and Execute
ptr->display(); // Compile and Execute
I am attempting to do something like:
class Base {
public:
Base() {
cout << typeid(*this).name() << endl;
}
...
};
class Derived : public Base { ... }
class MoreDerived : public Derived { ... }
Derived d;
MoreDerived m;
Problem is, I always get Base printed to the screen, when I need to see Derived and MoreDerived. Is there a way to get typeid to work this way with derived classes? Or is there another approach besides typeid?
Note: I am adding functionality to an already coded suite, so I don't want to have to add a virtual method to the base class where the derived classes return this value themselves. Also, not worried about runtime overhead, this will be part of a debug compile switch.
In the constructor Base(), the object is still a "Base" instance. It will become a Derived instance after the Base() constructor. Try to do it after the construction and it will work.
See for example :
Avoiding virtual methods in constructor
Never Call Virtual Functions during Construction or Destruction
You can't do that from within a constructor (or destructor) - neither with typeid nor with a virtual method. The reason is while you're in a constructor the vtable pointer is set to the base class being constructed, so the object is of base class and no amount of polymorphism will help at that point.
You have to execute that code after the most derived class has been constructed. One option would be to use a factory function:
template<class T>
T* CreateInstance()
{
T* object = new T();
cout << typeid(*object).name() << endl;
return object;
}
Another option is to provide a virtual toName() function
struct Object{
virtual std::string toName() const = 0;
}
struct Base: Object{
std::string toName()const{ return "Base"; }
}
struct Derived: Base, Object{
std::string toName()const{ return "Derived"; }
This might get tedious since you need to manually create each toName function. But the advantage it gives you is to provide your own custom name.
I have, for example, such class:
class Base
{
public: void SomeFunc() { std::cout << "la-la-la\n"; }
};
I derive new one from it:
class Child : public Base
{
void SomeFunc()
{
// Call somehow code from base class
std::cout << "Hello from child\n";
}
};
And I want to see:
la-la-la
Hello from child
Can I call method from derived class?
Sure:
void SomeFunc()
{
Base::SomeFunc();
std::cout << "Hello from child\n";
}
Btw since Base::SomeFunc() is not declared virtual, Derived::SomeFunc() hides it in the base class instead of overriding it, which is surely going to cause some nasty surprises in the long run. So you may want to change your declaration to
public: virtual void SomeFunc() { ... }
This automatically makes Derived::SomeFunc() virtual as well, although you may prefer explicitly declaring it so, for the purpose of clarity.
class Child : public Base
{
void SomeFunc()
{
// Call somehow code from base class
Base::SomeFunc();
std::cout << "Hello from child\n";
}
};
btw you might want to make Derived::SomeFunc public too.
You do this by calling the function again prefixed with the parents class name. You have to prefix the class name because there maybe multiple parents that provide a function named SomeFunc. If there were a free function named SomeFunc and you wished to call that instead ::SomeFunc would get the job done.
class Child : public Base
{
void SomeFunc()
{
Base::SomeFunc();
std::cout << "Hello from child\n";
}
};
Yes, you can. Notice that you given methods the same name without qualifying them as virtual and compiler should notice it too.
class Child : public Base
{
void SomeFunc()
{
Base::SomeFunc();
std::cout << "Hello from child\n";
}
};