Automatically downcast function arguments in C++ - c++

I have two classes, let's say Base and Derived:
class Base {
public:
virtual ~Base() = 0;
};
class Derived : public Base {};
and a function foo:
auto foo (Derived* d) {
...
}
Is it possible to automatically downcast its argument? So I could do something like this:
Base* b = new Derived();
foo(b);
Basically I would like to write this without explicit casting it before function call.
I read something about conversion operators/constructors but they seem not useful in my case, do you have any other idea?
Edit: Sorry, I oversimplified the question with 2 classes and just a function. But actually I've got a library of 50-ish functions and 3 classes (a superclass and 2 subclasses). This unfortunately makes the easiest and cleanest solutions unsuitable because in my opinion (correct me if I am wrong) they scale bad.

I can think of three possible solutions, depending on your needs. I've replaced raw pointers with unique_ptrs in my examples.
Case 1: You don't need the base type of each derived type to be the same.
Use CRTP to allow the base type to invoke itself as a derived type. Example implementation:
template <typename DerivedType>
class Base {
template <typename F>
auto invoke_as_derived(F&& f) {
return std::forward<F>(f)(static_cast<DerivedType*>(this));
}
};
class Derived : public Base<DerivedType> {};
Usage:
std::unique_ptr<Base<Derived>> b = std::make_unique<Derived>();
b->invoke_as_derived(foo);
Since you mentioned using a list of Base pointers, this probably won't work for you.
Case 2: You need a shared base type but only have one layer in your type hierarchy and no virtual methods.
Use std::variant and std::visit.
class Derived {};
using Base = std::variant<Derived, /* other derived types */>;
auto foo(Derived*) { ... }
class FooCaller {
operator ()(Derived& d) {
return foo(&d);
}
// Overload for each derived type.
}
Usage:
Base b = Derived();
std::visit(FooCaller{}, b);
Case 3: You need a single base type but also want virtual methods and/or additional layers in your type hierarchy.
You might try the visitor pattern. It takes some boilerplate, but it may be the best solution depending on your needs. Sketch of the implementation:
class Visitor; // Forward declare visitor.
class Base
{
public:
virtual void accept(Visitor& v) = 0;
};
class Derived : public Base
{
public:
void accept(Visitor& v) final { v.visit(*this); }
};
struct Visitor
{
virtual void visit(Derived&) = 0;
// One visit method per derived type...
};
struct FooCaller : public Visitor
{
// Store return value of call to foo in a class member.
decltype(foo(new Derived())) return_value;
virtual void visit(Derived& d)
{
return_value = foo(&d);
}
// Override other methods...
};
Usage:
std::unique_ptr<Base> b = std::make_unique<Derived>();
FooCaller foo_caller;
b->accept(foo_caller);
You could write a visitor that takes a function to apply to the element so you don't have to repeat this for all of your many functions. Alternatively, if you can alter the functions themselves, you could replace your functions with visitor types.
Edit: Simplifying the call syntax back down to foo(b)
Define an overload per function overload set to which you want to pass Base objects. Example, using the 3rd technique:
auto foo(Base* b) {
FooCaller foo_caller;
b->accept(foo_caller);
return std::move(foo_caller.return_value);
}
Now foo(b.get()) will delegate to the appropriate overload of foo at run-time.

The usual approach would not be to downcast, but to use virtual functions. I.e. put void foo() inside of the class.
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() { std::cout << "Base foo()\n"; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived foo()\n"; }
};
int main()
{
Base* b = new Derived();
b->foo();
delete b;
}
outputs:
Derived foo()
If you want to make it impossible to call Base::foo(), you can set
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
making Base an abstract class.
But if you really want to call foo(b), you can use a (templated) helper function. E.g.:
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived foo()\n";
}
};
template<typename T>
void foo(T* t)
{
t->foo();
}
int main()
{
Base* b = new Derived();
foo(b);
delete b;
}

Related

How to call virtual functions of a derived class through base class pointers, assuming functions in base class are not virtual

class Base
{
public:
virtual void f()
{
g();
}
virtual void g()
{
cout<<"base";
}
};
class Derived : public Base
{
public:
virtual void f()
{
Base::f();
}
virtual void g()
{
cout<<"derived";
}
};
int main()
{
Base *pBase = new Derived;
pBase->f();
return 0;
}
In this program I have kept both derived and base class functions as virtual. Is it possible call virtual functions of derived class through base class pointer and base class functions are not virtual.
Thanks in advance..
assuming functions in base class are not virtual
This can be achieved via type erasure. But there are caveats.
Your "base" class should decide between the two:
Being a view class (can't be called delete on or created by itself)
Being a resource owning class (implemented similar to 1, but stores a smart pointer).
Here is an example for case 1: https://godbolt.org/z/v5rTv3ac7
template <typename>
struct tag{};
class base
{
public:
base() = delete;
template <typename Derived>
explicit base(tag<Derived> t)
: _vTable(make_v_table(t))
{}
int foo() const { return _vTable.foo(*this); }
protected:
~base() = default;
private:
struct v_table
{
virtual int foo(const base &b) const = 0;
protected:
~v_table() = default;
};
template <typename Derived>
static const v_table& make_v_table(tag<Derived>){
struct : v_table
{
int foo(const base &b) const {
return static_cast<const Derived&>(b).foo();
}
} static const _vTable{};
return _vTable;
}
private:
const v_table& _vTable;
};
class derived : public base
{
public:
explicit derived()
: base(tag<derived>{})
{}
int foo() const { return 815; }
};
// example
#include <iostream>
int main(){
derived d{};
const base& b = d;
std::cout << b.foo() << '\n';
}
Take notice, that you can only take a pointer or a reference (cv-qualified) to a base class. The base class can't be created on its own.
Also tag<T> is needed to call a templated constructor.
DO NOT CALL DERIVED METHODS IN THE BASE CONSTRUCTOR OR DESTRUCTOR
Simple answer is no, if the function you are calling is not virtual. The Compiler would have no Idea that you are trying to call a function from the Derived Class, and won't make and I'm paraphrasing here since I do not know the proper term for,"Won't make proper entries in the Virtual Table".
class Base
{
public:
void f()
{
std::cout<<"Base f() Called\n";
g();
}
virtual void g()
{
std::cout<<"Base g()\n";
}
virtual ~Base(){std::cout<<"Base Destroyed\n";}
};
class Derived : public Base
{
public:
void f()
{
g();
}
virtual void g()
{
std::cout<<"Derived g()\n";
}
~Derived(){std::cout<<"Derived Destroyed\n";}
};
int main()
{
Derived* D1 = new Derived();
Base* B1 = D1;
B1->f();
delete B1;
return 0;
}
Have a look at the following code, I have not declared Base::f() as virtual,calling B1->f() calls the Base Method, but the base method calls a virtual function Base::g() and this allows the "Derived" method be called.
Have a look at this thread or this blogpost to understand Virtual Tables.
(1) and you must ALWAYS declare the destructor of a base class virtual when destroying Derived Object through a Base Pointer, else the resources used by the Derived Object will never get destroyed and it's memory will leak until the program closes.
Don't Take my word as gospel, I am simply passing on knowledge I have acquired from first hand experience, Except for (1), specially if you are not using smart pointers

Best way to handle a virtual method for copying a polymorphic object if its base class should not be abstract?

I need to copy an object of a polymorphic class having a base pointer. I know that I can implement a virtual method for this. But what if the base class should not be abstract? Leaving the method without pure-specifier can lead to run-time bugs, if you forget reimplement it in the derived. It's uncomfortable. What is the best way to handle this?
There are good reasons why you should never want to instantiate a base class.
If you do need to make a empty final class use the following.
class IBase
{
virtual void SharedCode()
{
1 + 1;
/// code here
};
virtual void AbstractDecalration() = 0;
};
class Base final: IBase
{
void AbstractDecalration() override;
};
Base b{};
All Future Derived classes will be able to use the SharedCode of IBase and you will have a Instantiated class of Base that is final. This is for future proofing your code base.
However I realize that is not the question you asked so here is a implementation were I use a simple check to the vtable pointer of the class to see if I have the correct class.
This is a runtime check and doesn't work across libraries use dynamic_assert if that is the case.
#include <memory>
#include <type_traits>
#include <assert.h>
class Base {
public:
auto clone() const
{
return std::unique_ptr<Base>(this->clone_impl());
}
private:
virtual Base* clone_impl() const
{
Base b{};
int* bVtablePtr = (int*)((int*)&b)[0];
int* thisVtablePtr = (int*)((int*)this)[0];
assert(bVtablePtr == thisVtablePtr);
return new Base(*this);
}
};
class Derived : public Base
{
auto clone() const
{
return std::unique_ptr<Derived>(this->clone_impl());
}
virtual Derived* clone_impl() const
{
return new Derived();
}
};
class Falty : public Base{};
int main(){
std::unique_ptr<Derived> good(new Derived());
std::unique_ptr<Falty> falty(new Falty());
good->clone(); // oke
falty->clone(); // this function asserts at runtime
}
Note the private clone_impl and public unique_ptr retuning clone method.
Very usefull to prevent memory leaks in your code
You can achieve what you want by introducing another abstract base class plus using CRPT for clone function. Then, clone will be automatically implemented in all derived classes "for free" (without manual retyping). Example:
struct Abstract
{
virtual ~Abstract() {}
virtual Abstract* clone() const = 0;
virtual void say() const = 0;
};
template <typename B, typename D>
struct AbstractCloneable : B
{
virtual B* clone() const override
{
return new D(static_cast<const D&>(*this));
}
};
// original base class
struct Base : AbstractCloneable<Abstract, Base>
{
virtual void say() const override
{
std::cout << "Base" << std::endl;
}
};
// original derived class #1
struct Derived1 : AbstractCloneable<Base, Derived1>
{
virtual void say() const override
{
std::cout << "Derived1" << std::endl;
}
};
And a test program:
int main()
{
std::unique_ptr<Abstract> ptr1 = std::make_unique<Base>();
ptr1->say();
std::unique_ptr<Abstract> ptr1_copy{ ptr1->clone() };
ptr1_copy->say();
std::unique_ptr<Abstract> ptr2 = std::make_unique<Derived1>();
ptr2->say();
std::unique_ptr<Abstract> ptr2_copy{ ptr2->clone() };
ptr2_copy->say();
}
Which outputs:
Base
Base
Derived1
Derived1
Live demo: https://godbolt.org/z/3FeSTd
See this article for more details and explanations: C++: Polymorphic cloning and the CRTP (Curiously Recurring Template Pattern).

How to use derived parameter in an overriding function without dynamic casting

Can anyone let me know how to achieve:
the parameter of a method of a derived class being the parameter's
derived class (not the parameter's base class)?
This is what I want:
class Base{
public:
// Base class method has ParameterBase parameter
virtual void f(ParameterBase pb) = 0;
}
class Derived : public Base{
public:
// I want: Derived class method has ParameterDerived parameter;
void f(ParameterDerived pd){ //do something with pd; }
}
class ParameterBase{
// Base class of parameter;
}
class ParameterDerived : public ParameterBase{
// Derived class of parameter;
}
How to achieve above?
Do I have to use ParamterBase in the derived method's parameter list and dynamic_cast the parameter in the method body?
The feature you are asking for is called parameter type contra-variance. And C++ unfortunately, doesn't support it. C++ supports just the return type covariance. See here for a nice explanation.
Perhaps inconveniently, C++ does not permit us to write the function
marked hmm... above. C++’s classical OOP system supports “covariant
return types,” but it does not support “contravariant parameter
types.”
But you can use dynamic_cast<>() operator. But first, you must change the parameter type to pointer or reference, and add at least one virtual member (virtual destructor counts too) to your class ParameterBase to make compiler to create virtual method table for it. Here is the code with references. Pointers can be used instead.
class ParameterBase
{
public:
// To make compiler to create virtual method table.
virtual ~ParameterBase()
{}
};
class ParameterDerived : public ParameterBase
{
};
class Base
{
public:
// Pointers or references should be used here.
virtual void f(const ParameterBase& pb) = 0;
};
class Derived : public Base
{
public:
virtual void f(const ParameterBase& pb) override
{
// And here is the casting.
const ParameterDerived& pd=dynamic_cast<const ParameterDerived&>(pb);
}
};
int main()
{
Derived d;
ParameterDerived p;
d.f(p);
}
Supposing you want Derived to be called with ParameterDerived, but you also want to declare the interface in abstract base classes.
The interface MUST have the same parameter types, but you can still enforce the right parameter subclass with a dynamic_cast inside Derived::f
#include <iostream>
#include <string>
// interface
struct ParameterBase {
virtual ~ParameterBase() {};
};
struct Base {
virtual void f(ParameterBase *pb) = 0;
virtual ~Base() {};
};
// specific
struct ParameterDerived : public ParameterBase {
std::string name;
ParameterDerived(const std::string &name) : name(name) {}
ParameterDerived& operator=(const ParameterDerived& rhs) { name = rhs.name; }
~ParameterDerived() {};
};
struct Derived : public Base {
Derived(){}
Derived& operator=(const Derived &rhs) {}
virtual ~Derived(){}
void f(ParameterBase *pb) {
ParameterDerived *pd = dynamic_cast<ParameterDerived*>(pb);
if (pd) {
std::cout << "Derived object with derived parameter " << pd->name << std::endl;
} // else {throw std::exception("wrong parameter type");}
}
};
int main() {
Derived object;
ParameterDerived param("foo");
object.f(&param);
}

Is it possible to create an instance of a class within the same class?

Say I have a class:
class Foo{
public:
Foo(){
}
//Is it possible to create a function like this:
virtual Foo* createOb(){
//Should create a new Foo,Bar or Fiz, depending on the actual object type.
}
}
class Bar: public Foo{
public:
Bar(){
}
}
class Fiz: public Foo{
public:
Fiz(){
}
}
Is it possible to have a method createOb() in the base class, so when createOb() is called on an instance of one of the derived classes, that an instance of the derived class is created ?
Yes, it can be done, using CRTP.
Bu first, returning a raw pointer obtained from new is very dangerous. In c++ raw pointers should be used only when they do not have ownership of the pointed object. So I took the liberty to use unique_ptr:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base>
{
return std::unique_ptr<Base>{};
}
};
// abstract works too:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base> = 0;
};
template <class Derived>
struct Base_crtp : Base {
auto create_obj() -> std::unique_ptr<Base> override /* final */
{
return std::unique_ptr<Base>{new Derived{}};
}
};
struct D1 : Base_crtp<D1>
{
};
struct D2 : Base_crtp<D2>
{
};
And then:
auto b1 = std::unique_ptr<Base>{new D1{}};
auto b2 = std::unique_ptr<Base>{new D2{}};
auto new_d1 = b1->create_obj();
auto new_d2 = b2->create_obj();
Definitely YES!!!
When a method is declared virtual in base class, and called through the derived class object, then the derived class function gets called (Read vprt, vtable concept in c++).
#include <iostream>
using namespace std;
class A{
public:
virtual A* getobj(){
return new A();
}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
virtual A* getobj(){
return new B();
}
};
int main()
{
A *a = new B();
A *second = a->getobj();
return 0;
}
In the above code, we are calling the getobj() function using class B's object.
Here the constructor of class B is called twice.
first, for new B() in main
secondly for getobj function call which again creates object of B
This is not an optimal solution, but it works.
In your .h
class Foo{
public:
Foo();
virtual Foo* createOb();
};
class Bar: public Foo{
public:
Bar();
};
class Fiz: public Foo{
public:
Fiz();
};
In your .cpp
#include "Header.h"
Foo::Foo() {}
Foo* Foo::createOb(){
if (dynamic_cast<Bar*>(this)) {
return new Bar();
}
else if (dynamic_cast<Foo*>(this)) {
return new Foo();
}
return nullptr;
}
Bar::Bar() {}
Fiz::Fiz() {}
As already suggested please consider a pure virtual method
No, this is not possible with "pure" inheritance. The classes must override createOb() member function in order to support cloning.
You can see why this is not possible by considering separate compilation of classes. An implementation of one-fits-all createOb() member function must be completed in isolation from Bar and Fiz, making it impossible for the base to know the type of its subclasses.
An implementation with a pure virtual function in the base is very common, though.
Another approach is to use Curiously Recurring Template Pattern (CRTP) to implement cloning. This article explains how it can be done.

base class pointer, invoke method based on derived type

I understand that the following code doesn't work -- can't convert base to foo.
Is there something I can do, or some pattern to employ which would get me close the behavior I'm trying to achieve in the code below? IOW, if I have a base class pointer to a derived type, how can I invoke a specific method that matches the derived type (not the base type)?
What patterns might I use? I looked into Curiously Recursive (or recurring) Template Pattern, however this imposed other limitations itself.
class base {};
class foo : public base {};
void method(const foo& f){}
int main(){
base* b = new foo();
method(*b);
}
The easiest way is probably to just make method() a virtual member function on foo:
class base {
public:
virtual void method() const = 0;
};
class foo : public base {
public:
void method() const override { }
};
int main(){
foo f;
base* b = &f;
b->method();
}
But if for some reason that is not possible (perhaps you don't have access to method() or perhaps you want to keep the logic in method() separate from foo) you could use a simplified version of the Visitor Pattern.
The visitor pattern relies on all the classes in your hierarchy having a virtual function to dispatch based on class type.
In your case you don't need double-dispatch so you don't actually need the visitor object and can just call your method function directly from a virtual dispatch function:
class base {
public:
virtual void dispatch() const = 0;
};
class foo : public base {
public:
void dispatch() const override;
};
void method(const foo& f){}
void foo::dispatch() const {
method(*this);
}
int main(){
foo f;
base* b = &f;
b->dispatch();
}
You have to remember that in most contexts the compiler doesn't know that your base pointer is actually of type foo.
Use virtual functions to solve these kinds of problems:
class base {
public:
virtual void func() const { /* A */ }
};
class foo : public base {
public:
void func() const override { /* B */ }
};
void method(const base& f) {
f.func();
}
int main(){
base* b = new foo();
method(*b);
}
Now, depending on the actual type of f, either A or B code will be executed in method.