Still getting the hang of c++ classes, and I'm wondering what is the most run-time-efficient way to accomplish this:
I have a derived class that I want to instantiate once (known at compile-time), but I want to typecast the pointer to a base class pointer and pass that around for the rest of my program to use. That way, if I have a future project where I want to change the instance from animal.dog to animal.cat, all other parts of my code will still be able to call the method animalPtr->eat(), but the actual behavior will be specific to dog or cat. I will only ever have 1 instance of animal.dog or animal.cat, and I will never have an instance of base-class animal.
Maybe doing exactly what I just described is exactly how I need to do it, but I read some online arguments about the pros and cons of having the base class "animal" use virtual functions versus having the base class be a template class (not exactly sure how to even make it into a template in this case....to me, templates classes looked like they were used for creating generic data types for the members, but that is not what I'm needing here).
Any help? Remember that speed-performance is the highest priority for me.
Using a virtual function is the object oriented way to solve this. With the usual implementation of virtual functions, it adds another pointer indirection and makes inlining impossible so if you really, really, really have performance issues and the function is small and called millions of times in a tight loop, then you might have a performance issue.
Use the virtual function approach to start with. If it is a problem (and you have measured that this is indeed the problem with a profiler), then you can look into changing things to a template based approach that might be more efficient.
to implement what you want w/o virtual functions can be done by templating the base class:
template<class Parent>
class BASE {
public:
BASE();
virtual ~BASE();
void func() {
reinterpret_cast<Parent*>(this)->func(); // call parent func
// or
(Parent*)(this)->func();
}
};
You can later typedef the BASE class to a normal class name:
typedef BASE<specific_Parent> myBASE;
It seems to me you are trying to decide between run-time and compile-time polymorphisms. If you do really need run-time polymorphism you have to use virtual functions. But if you don't really need run-time polymorphism, you can use CRTP to achieve the compile-time polymorphism.
This is a very primitive example illustrating the compile-time polymorphism (code on ideone.com):
#include <iostream>
namespace so {
template<typename _t_derived_>
class _animal_ {
private:
using _derived_ = _t_derived_;
public:
void eat() const {
static_cast<_derived_ const *>(this)->eat_impl();
}
};
class _dog_: public _animal_<_dog_> {
friend class _animal_<_dog_> ;
private:
using _base_ = _animal_<_dog_>;
protected:
void eat_impl() const {
std::cout << "dog's eating." << std::endl;
}
};
class _cat_: public _animal_<_cat_> {
friend class _animal_<_cat_> ;
private:
using _base_ = _animal_<_cat_>;
protected:
void eat_impl() const {
std::cout << "cat's eating." << std::endl;
}
};
template<typename _t_animal_>
void feed(_t_animal_ const & _animal) {
std::cout << "feeding an animal: ";
_animal.eat();
}
} // namespace so
int main() {
so::_dog_ dog_;
so::_cat_ cat_;
so::feed(dog_);
so::feed(cat_);
return (0);
}
Program output:
feeding an animal: dog's eating.
feeding an animal: cat's eating.
Related
I'm a new to OOP and trying to learn C++ and I came cross polymorphism and using the virtual keyword.
I just don't understand why we might need to do that.
I've checked this site for similar questions but none of them attempts to answer that why?
The main goal is: Separation of concerns.
Let's take an example from my day job. I work on a codebase that does networking. The vast majority of the codebase depends on a class that looks like:
class Transport
{
public:
virtual bool SendMessage(int clientId, string message);
};
Imagine I've got hundred files, and tens of thousand of lines of code, using this class.
Now, my colleague in the low-level team wants to allow our code to use both UDP and TCP for communications. They can simply implement:
class UdpTransport:public Transport
{
public:
bool SendMessage(int clientId, string message) override { /* their code */};
};
class TcpTransport:public Transport
{
public:
bool SendMessage(int clientId, string message) override { /* their code */};
};
This allows me to keep the whole of my code unchanged (using only Transport* or Transport&) and not have to worry about what a UdpTransport or TcpTransport is. It allows one part of the code to work without knowing what another part of the code is doing.
Most introductions of polymorphism start with something like this:
Base* b = new Derived(); // ouch :/
This is very unfortunate in my humble opinion, because it creates the misunderstanding that polymorphism implies manual memory managment via new. The topics are somewhat related. Though my example of polymorphism would start like this:
#include <iostream>
struct base {
virtual void say_hello() { std::cout << "hello base\n"; }
};
struct derived : base {
void say_hello() override { std::cout << "hello derived\n";}
};
void foo(base& b) {
b.say_hello();
}
int main()
{
base b;
derived d;
foo(b);
foo(d);
}
say_hello must be declared virtual to allow derived to override the method. If say_hello was not virtual then derived::say_hello would not override it.
If you remove virtual and override above you can see what happens when the method in the derived class does not override the method in the base class. The call b.say_hello() would then call base::say_hello() no matter if a base or derived is passed to foo because only for virtual methods the method to be called considers the dynamic type of the object.
What are the use cases for a base class pointer pointing to a derived class object
Same as the reference above. foo(base&) can take an object of any type that derives from base and then call its say_hello method. If this wasnt possible you would have to write a foo(derived), foo(derived2), foo(derived3) to call their say_hello method. In a nutshell, polymorphism means to treat different types the same. foo does not need to know what the dynamic type of its paramter is. It only needs to know that it inherites from base.
Many Design Patterns (GOF book) rely on virtual functions. The idea is that you have you work with an object of which you only know it's interface and when you call a function, what is done is based on the object that implements the interface.
One of the design patterns is Command where you have a container in which you can add command implementations and the handler of the container calls the "execute" function without having to worry about what the command actually is. The command implementation contains already the data it needs to run.
A common alternative for virtual functions is a switch case that needs to know all the implementations as an enum so the caller knows what to call exactly or an own implementation of a function-table.
Of course, if you don't see how such thing can improve your program, then it's best not to try and force it in.
Consider the following class architecture and function:
#include <iostream>
#include <string>
class Base
{
public:
std::string hello() const
{
return "Hello Base!";
}
};
class Derived : public Base
{
public:
std::string hello() const
{
return "Hello Derived!";
}
};
void outputHello(const Base& b)
{
std::cout << b.hello() << '\n';
}
We have:
A base class with a hello() method that returns "Hello Base!";
A derived class with a hello() method that returns "Hello Derived!";
A outputHello(const Base&) function that takes a reference to a Base object as its argument and prints out the result of a call to its hello() method.
Now, what do you think the following program will output?
int main()
{
Base b;
outputHello(b);
Derived d;
// Allowed as a reference/pointer to Base can
// reference/point to a Derived object
outputHello(d);
}
You probably guessed the following if you come from Java or a similar object-oriented language:
Hello Base!
Hello Derived!
But it instead it outputs Hello Base! twice. Why? It's actually quite simple. When the compiler gets to the outputHello function body it sees std:cout << b.hello() << '\n'. It thinks: Well, b is of type Base, so I'm gonna issue a call to Base::hello(). And it does exactly that, regardless of the type of the object we actually pass as argument to outputHello.
To solve this problem and get the output we expected, we need RTTI (Runtime Type Information), whose name speaks for itself. This is achieved by marking Base::hello() as virtual:
class Base
{
public:
virtual std::string hello() const
{
return "Hello Base!";
}
};
It is also good practice to mark Derived::hello() as override, though it is not necessary — override functions are automatically virtual.
class Derived : public Base
{
public:
std::string hello() const override
{
return "Hello Derived!";
}
};
We then get our expected output.
I have an idea to architecting classical entity-component in a better way with variadic template inheritance. This question stems from funky experiments in the context of 3d-graphics but i believe i have it broken down to a very abstract question about C++. I am able to use C++20 in the scope in which it is currently implemented in Microsoft cl aka. the MSVC++19-Toolchain.
So. A few Base classes:
class basic {
public:
std::wstring get_name() { return name; }
virtual void do_something_idk_virtual() = 0;
virtual ~basic() {}
private:
std::wstring name;
}
class has_legs {
public:
virtual void walk() = 0;
virtual ~has_legs() {}
}
class has_wings {
public:
virtual void fly() = 0;
virtual ~has_wings() {}
}
template<typename... Ts>
class entity : public basic, public Ts... {
public:
virtual ~entity() {}
}
So far, so good. Now i want to make a duck:
class duck : entity<has_wings, has_legs> {
public:
virtual ~duck() {}
virtual void walk() { cout << "walk" << endl; }
virtual void fly() { cout << "fly" << endl; }
virtual void do_something_idk_virtual() { } // nothing,
}
still, seems to work. The problem is: I know have data structure (say a linked_list, or some sort of graph) and I use the visitor-pattern to work with basic*-typed things. I now have a lot of Code that looks like this. This is, quite literally, the central and critical part of a my program:
void visit(basic* node) {
//here i find out, through magic or some other kind of out-of-scope-mechanism that node is at least a has_wings. Problem:
reinterpret_cast<has_wings*>(node)->fly(); //does not work, will call basic::do_something_idk_virtual(). As far as i understand, this is because the compiler-generated vtable does not change via the reinterpret_cast.
reinterpret_cast<entity<has_wings>*>(node)->fly(); //might, work, problems start to come in if node is of some type that has_wings and has_legs. It sometimes calls some other method, depending on the ordering in declaring the class.
}
Solution
Have every component (aka. the pure interfaces) and the entity-class virtually inherit from basic
in basic add the non-virtual method:
template<typename TComponent> TComponent* get_component() {
return dynamic_cast<TComponent*>(this);
}
This will then fix vtables. I am not sure why dynamic_cast does that.
First of all, your template gives you nothing. class duck : public basic, public has_wings, public has_legs is absolutely identical.
Second, you need to decide what your level of polymorphic access is. If your level is basic, than it has to have already defined all the virtuals you want to be accessing (i.e. has_wings, fly) An interface where you need dynamic_casts to arrive to correct dynamic type (your example with reinterpret_cast is just wrong, you can't use reinterpret_cast to move through class hierarchy) is a poorly written interface.
Sometimes visitor pattern can be employed, but in my mind, it tends to produce extremely hard to troubleshoot code.
You have to use static_cast or dynamic_cast to move within an inheritance hierarchy, and static_cast can’t descend virtual inheritance or cross-cast (in one step) because the layout of different classes that derive from the source and destination types may differ. As it is, you’d have to know the actual type (not just that it had a given aspect) to do the conversion. If you have your “aspect” classes inherit from basic—virtually, so that there is a unique basic* to be had—you can then use dynamic_cast not for its checking purpose but so as to find the appropriate vtable for the aspect in question.
If you can’t afford that, you may want to amalgamate the interfaces somehow. You then have to be careful to call the functions only when they’re meaningful; that’s already the case (“through magic”), but then the ordinary call syntax might be an attractive nuisance. You might also try some C-style polymorphism with a manually-created vtable with function pointers for each optional behavior.
I was looking at several SO posts (listed below) regarding the benefit of using base class pointer to a derived class object. But in most of the cases, virtual function is the ultimate purpose of using base class pointer. I added comments to some of these posts, but I guess since the posts are old, responses were not received.
Now my question is, if we do not use virtual function concept, are there any purpose of using base class pointer in some other case?
In the code below,
pEmp->computeTotalSalary
calls base class function since virtual function is missing. This is expected behavior.
#include <iostream>
using namespace std;
class Employee
{
public:
void computeTotalSalary ()
{
cout<<"Computing Employee Salary in Base Class:"<<endl;
}
};
class TeachingStaff : public Employee
{
public:
// Override the function
void computeTotalSalary ()
{
cout<<"Computing Teacher's Salary in Sub class: "<<endl;
}
};
int main()
{
TeachingStaff *pTeacher = new TeachingStaff() ;
pTeacher->computeTotalSalary();
Employee *pEmp;
pEmp = pTeacher;
pEmp->computeTotalSalary();
pTeacher->Employee::computeTotalSalary();
}
Links:
1. Why use base class pointers for derived classes
A Base Class pointer can point to a derived class object. Why is the vice-versa not true?
assigning derived class pointer to base class pointer in C++
Using a base class pointer or reference allows you to write functions that accept all derived classes of the base generically so you can call common non-virtual functions on them. Otherwise, you'd have to write the same function multiple times for the different derived classes, or use templates.
#include <iostream>
class base_t {
public:
void non_virtual() const { std::cout << "Hello, World!\n"; }
};
class derived_1_t : public base_t { };
class derived_2_t : public base_t { };
void do_something(const base_t& obj) {
obj.non_virtual();
}
int main() {
derived_1_t var1;
derived_2_t var2;
do_something(var1);
do_something(var2);
}
While you can intentionally hide functions from the base class, it is most often an unintentional mistake (or poor design) to do so. The C++11 override keyword was introduced to help prevent this mistake.
There are other use cases for inheritance beyond virtual functions and polymorphism. For instance: (1) one might put a bunch of objects in a heterogeneous container such as std::vector<Employee*> where it doesn't need access to the derived class data, though this is probably suspect without polymorphism also, (2) inheriting behavior or POD data members (also questionable practice), or (3) inheriting for policy-based design (see Alexandrescu's Modern C++ Design).
Generally, you also want a destructor for inheritance roots. Herb Sutter says, "A base class destructor should be either public and virtual, or protected and nonvirtual."
You might also consider not using inheritance in this way. See "Better Code: Runtime Polymorphism" by Sean Parent, which may just blow your mind.
I have a vector with pointers of type Vehicle. Vehicle is the base class and there are many derived types like MotorCycle, Car, Plane, etc. Now, in my program there comes a point where I need the derived type while traversing the vector. Each Vehicle class has a GetType() function which returns an int which tells me what the derived type is (motorcylce, car, plan). So, I can use a dynamic cast to downcast to the derived type from the base class pointer. However, I need to have a giant if statement everytime I need the derived pointer
if(vehicle_ptr->GetType() == PLANE)
Plane *ptr = dynamic_cast<Plane*> vehicle_ptr;
else if (vehicle_ptr->GetType() == MOTORCYCLE)
MotorCycle *ptr = dynamic_cast<MotorCycle*> vehicle_ptr;
..and on and on.
Is there a way to have a function or some trick I can call that would save me from the giant if statement everywhere? Like ::GetDerivedPtr(Vehicle *ptr). Would a template class help here? (never used them before) Sorry, my C++ is a bit rusty and I did search but these terms bring up too much material to find what I'm looking for. Thanks.
It looks like you've manually tried to recreate polymorphism. You don't need a type member. This is almost always a bad idea. Use polymorphism and virtual functions.
When you have a vehicle pointer v and do
v->function();
It will call the proper function for whatever type (Plane, Train, or Automobile) that the pointer actually points to if function is a virtual function. What you're doing is already handled by the language.
So:
class A {
public:
virtual void f() {cout << "A";}
};
class B : public A {
public:
virtual void f() {cout << "B";}
};
int main(){
A *a;
B b;
a = &b;
a->f();
}
The above snippet will print B.
I second the idea that you need some virtual function and a common base type. Imagine that there is some way to get the pointer which has the correct type. What will you do with it then? You'll have to make a giant switch anyway, because you call specific functions for each of your specific types.
One solution would be to invent a name for the operation you are trying to execute, and put its implementation as a virtual function at each specific Vehicle class. If the operation accepts different parameter for each of the cases, the parameters have to be packed into a special polymorphic structure/class, but here maybe the Visitor pattern is a more generic solution.
First check whether what you're going to do can be done simply via virtual functions in class Vehicle, overridden by each derived class.
If not, then consider the Visitor Pattern.
Cheers & hth.,
dynamic_cast will check the type itself (you don't need your own variable for this). You can do the following instead:
Plane *plane_ptr = dynamic_cast<Plane*>(vehicle_ptr);
if(plane_ptr != NULL)
{
// Do stuff with 'plane_ptr' that you couldn't do with 'vehicle_ptr'
}
I don't really see how creating a function to do the cast would help because you still need to class specific code anyway (and the function would have a fixed return type, so the closest you could get is something like the 'dynamic_cast' call, which is pretty much a standard function anyway).
Use Visitor based dispatching. Observe that not a simple cast of any kind is required in the follwing (somewhat trivialized) example:
// simple cyclic visitor
class VehicleVistor {
public:
// add overload for each concrete Vehicle type
virtual void Visit(class Motorcycle&) {};
virtual void Visit(class Plane&) {};
virtual void Visit(class Car&) {};
};
class Vehicle {
public:
virtual Accept(VehicleVisitor&) = 0;
};
class Car : public Vehicle {
public:
virtual Accept(VehicleVisitor& pVisitor) {
pVisitor.Visit(*this);
}
};
// and so on...
At some point of you program you need to retrieve all instances of, say Motorcycle:
class MotorcycleExtractingVisitor : public VehicleVisitor {
std::vector<Motorcycle*> mMotorcycles;
public:
void operator()(Vehicle* pVehicle) {
pVehicle->Accept(*this);
}
void Visit(Motorcycle& pMotorcycle) {
mAllMotorcycles.push_back(pMotorcycle);
}
std::vector<Motorcycles*> Get() { return mAllMotorcycles; }
};
class Extractor {
public:
// here you extract motorcycles
static std::vector<Motorcycle*> ExtractMotorcycles(std::vector<Vehicle*>& pVehicles) {
MotorcycleExtractingVisitor tMotos;
std::for_each(pVehicles.begin(), pVehicles.end(), tMotos);
return tMotos.Get();
}
// this would be a templatized version, left as exercise to the reader
template<class TExtracted, classtypename TBegItr, typename TEndItr>
static std::vector<TExtracted*> Extract(TBegItr pBeg, TEndItr pEnd) {
ExtractingVisitor<TExtracted> tRequiredVehicles;
std::for_each(pBeg, pEnd, tRequiredVehicles);
return tRequiredVehicles.Get();
}
};
Usage is as follows:
// fixed type version:
std::vector<Motorcycles*> tMotos =
Extractor::Extract(tVehicleVector);
// templatized version (recommended)
std::vector<Motorcycles*> tMotos =
Extractor::Extract<Motorcycles>(
tVehicleVector.begin(),tVehicleVector.end());
I know that it's OK for a pure virtual function to have an implementation. However, why it is like this? Is there conflict for the two concepts? What's the usage? Can any one offer any example?
In Effective C++, Scott Meyers gives the example that it is useful when you are reusing code through inheritance. He starts with this:
struct Airplane {
virtual void fly() {
// fly the plane
}
...
};
struct ModelA : Airplane { ... };
struct ModelB : Airplane { ... };
Now, ModelA and ModelB are flown the same way, and that's believed to be a common way to fly a plane, so the code is in the base class. However, not all planes are flown that way, and we intend planes to be polymorphic, so it's virtual.
Now we add ModelC, which must be flown differently, but we make a mistake:
struct ModelC : Airplane { ... (no fly function) };
Oops. ModelC is going to crash. Meyers would prefer the compiler to warn us of our mistake.
So, he makes fly pure virtual in Airplane with an implementation, and then in ModelA and ModelB, put:
void fly() { Airplane::fly(); }
Now unless we explictly state in our derived class that we want the default flying behaviour, we don't get it. So instead of just the documentation telling us all the things we need to check about our new model of plane, the compiler tells us too.
This does the job, but I think it's a bit weak. Ideally we instead have a BoringlyFlyable mixin containing the default implementation of fly, and reuse code that way, rather than putting code in a base class that assumes certain things about airplanes which are not requirements of airplanes. But that requires CRTP if the fly function actually does anything significant:
#include <iostream>
struct Wings {
void flap() { std::cout << "flapping\n"; }
};
struct Airplane {
Wings wings;
virtual void fly() = 0;
};
template <typename T>
struct BoringlyFlyable {
void fly() {
// planes fly by flapping their wings, right? Same as birds?
// (This code may need tweaking after consulting the domain expert)
static_cast<T*>(this)->wings.flap();
}
};
struct PlaneA : Airplane, BoringlyFlyable<PlaneA> {
void fly() { BoringlyFlyable<PlaneA>::fly(); }
};
int main() {
PlaneA p;
p.fly();
}
When PlaneA declares inheritance from BoringlyFlyable, it is asserting via interface that it is valid to fly it in the default way. Note that BoringlyFlyable could define pure virtual functions of its own: perhaps getWings would be a good abstraction. But since it's a template it doesn't have to.
I've a feeling that this pattern can replace all cases where you would have provided a pure virtual function with an implementation - the implementation can instead go in a mixin, which classes can inherit if they want it. But I can't immediately prove that (for instance if Airplane::fly uses private members then it requires considerable redesign to do it this way), and arguably CRTP is a bit high-powered for the beginner anyway. Also it's slightly more code that doesn't actually add functionality or type safety, it just makes explicit what is already implicit in Meyer's design, that some things can fly just by flapping their wings whereas others need to do other stuff instead. So my version is by no means a total shoo-in.
Was addressed in GotW #31. Summary:
There are three main reasons you might
do this. #1 is commonplace, #2 is
pretty rare, and #3 is a workaround
used occasionally by advanced
programmers working with weaker
compilers.
Most programmers should only ever use #1.
... Which is for pure virtual destructors.
There is no conflict with the two concepts, although they are rarely used together (as OO purists can't reconcile it, but that's beyond the scope of this question/answer).
The idea is that the pure virtual function is given an implementation while at the same time forcing subclasses to override that implementation. The subclasses may invoke the base class function to provide some default behavior. The base cannot be instantiated (it is "abstract") because the virtual function(s) is pure even though it may have an implementation.
Wikipedia sums this up pretty well:
Although pure virtual methods
typically have no implementation in
the class that declares them, pure
virtual methods in C++ are permitted
to contain an implementation in their
declaring class, providing fallback or
default behaviour that a derived class
can delegate to if appropriate.
Typically you don't need to provide base class implementations for pure virtuals. But there is one exception: pure virtual destructors. In fact if your base class has a pure virtual destructor, it must have an implementation. Why would you need a pure virtual destructor instead of just a virtual one? Typically, in order to make a base class abstract without requiring the implementation of any other method. For example, in a class where you might reasonably use the default implementation for any method, but you still don't want people to instantiate the base class, you can mark only the destructor as pure virtual.
EDIT:
Here's some code that illustrates a few ways to call the base implementation:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0;
};
class Der : public Base
{
public:
void DoIt();
};
void Base::DoIt()
{
cout << "Base" << endl;
}
void Der::DoIt()
{
cout << "Der" << endl;
Base::DoIt();
}
int main()
{
Der d;
Base* b = &d;
d.DoIt();
b->DoIt(); // note that Der::DoIt is still called
b->Base::DoIt();
return 0;
}
That way you can provide a working implementation but still require the child class implementer to explicitely call that implementation.
Well, we have some great answers already.. I'm to slow at writing..
My thought would be for instance an init function that has try{} catch{}, meaning it shouldn't be placed in a constructor:
class A {
public:
virtual bool init() = 0 {
... // initiate stuff that couldn't be made in constructor
}
};
class B : public A{
public:
bool init(){
...
A::init();
}
};