I'd like to achieve something like this below:
class A {
public:
virtual void reset() {
// 1). if there's no override to this function,
// then whatever derived from A should get reset
// to its constructed state, e.g. if B derives from
// A, then *this = B();
// 2). if there is an override to reset in the derived
// class, call the reset in the derived class
}
};
class B: public A {
public:
B() { std::cout<<"reset B"<<std::endl; }
// no override of reset() here
};
class C: public A {
public:
void reset() override {
std::cout<<"reset C"<<std::endl;
}
};
N.B. A doesn't know which class will derive from it, but whoever derive from it, if there is no reset() override in that derived class, calling A::reset() should reset the derived class object to its constructed state, i.e.
A* a = new B();
a->reset(); // -> this equals to *a = B();
However, if there is an override of reset() in the derived class, calling A::reset() should call the overridden reset(), i.e.
A* a = new C();
a->reset(); // -> this should call C::reset()
As mentioned in my comment it can be solved with the help of the CRTP, and another level of inheritance:
// The base class is just an abstract interface class
struct A
{
virtual void reset() = 0;
};
template<typename T>
struct realA : public A
{
void reset() override
{
*this = T();
}
}
class B : public realA<B>
{
... whatever you need here...
};
Now you can do
A* a = new B;
a->reset();
and it should work as you seemingly want it.
You have the (now abstract) base class A which contains the interface needed. Then you have the template class realA which contains the implementation you have in your variant of the A class, most notably the reset function implementation. Then the classes like B (and C and others) which inherits from realA instead of A.
Apart from the accepted answer, there is an alternative approach.
A* a = new Derived();
if(typeid(&A::reset)==typeid(&Derived::reset))// no override
{ *a = Derived(); } // instead of calling a1->reset()
else { a->reset(); } // if there is override
The problem with the above is that only public member functions can be used.
Related
There is another way to call derived class method from a base pointer object without casting?
class Base
{
};
class Derived : public Base
{
public:
void set() {printf("bbbbbbbbbbbb"); }
};
int main()
{
Base* pbBase;
pbBase = new Derived();
//pbBase->set(); // Compilation error.
(Derived*)pbBase->set(); // Working.
}
You can add virtual methods in Base that you override in Derived.
Note that you should make the destructor virtual too or else the derived class' destructor would not get called when you delete the object through a base class pointer.
#include <iostream>
class Base
{
public:
virtual ~Base() = default;
virtual void set() = 0; // = 0 makes it pure virtual
};
class Derived : public Base
{
public:
void set() override { std::cout << "bbbbbbbbbbbb\n"; }
};
int main()
{
Base* pbBase;
pbBase = new Derived();
pbBase->set();
delete pbBase;
}
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;
}
I have an object that is referenced by a pointer to its superclass: Base* d1 = new Derived();
I would like to pass it to another method that expects an object of the derived class: void f(Derived* d);
But it doesn't work unless I use type-casting. Is there another way to achieve this?
Here is an example:
#include <stdio>
class Base {};
class Derived : public Base {};
class Client
{
public:
void f(Base* b) { printf("base"); };
void f(Derived* d) { printf("derived"); };
};
int main(int argc, char* argv[])
{
Client* c = new Client();
Base* b = new Base();
Base* d1 = new Derived();
Derived* d2 = (Derived*) d1;
c->f(b); // prints "base". Ok.
c->f(d1); // prints "base"! I expected it to be "derived"!
c->f(d2); // prints "derived". Type-casting is the only way?
}
Generally speaking, you can do some stuff with dynamic_cast.
From the other side I believe, that dynamic_cast can practically always be avoided by the good design.
In your example you can make function f virtual member of Base class and override it in the Derived class. Then call it f via pointer to Base.
Something like this:
class Base {
public:
virtual void f() {
printf("Base\n");
}
};
class Derived : public Base {
public:
virtual void f() {
printf("Derived\n");
}
};
class Client
{
public:
void f(Base* b) {
b->f();
};
};
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.
I have following
class base
{
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
now I have
base* pbase = new derived();
pbase->myFunc();
I am getting error myFunc is not a member function of base.
How to avoid this? and how to make myFunc get called?
Note I should have base class contain no function as it is part of design and above code is part of big function
If you are adamant that this function should NOT be a part of base, you have but 2 options to do it.
Either use a pointer to derived class
derived* pDerived = new derived();
pDerived->myFunc();
Or (uglier & vehemently discouraged) static_cast the pointer up to derived class type and then call the function
NOTE: To be used with caution. Only use when you are SURE of the type of the pointer you are casting, i.e. you are sure that pbase is a derived or a type derived from derived. In this particular case its ok, but im guessing this is only an example of the actual code.
base* pbase = new derived();
static_cast<derived*>(pbase)->myFunc();
myfunc needs to be accessible from the base class, so you would have to declare a public virtual myfunc in base. You could make it pure virtual if you intend for base to be an abstract base class, i.e one that cannot be instantiated and acts as an interface:
class base
{
public:
virtual void myfunc() = 0; // pure virtual method
};
If you ant to be able to instantiate base objects then you would have to provide an implementation for myfunc:
class base
{
public:
virtual void myfunc() {}; // virtual method with empty implementation
};
There is no other clean way to do this if you want to access the function from a pointer to a base class. The safetest option is to use a dynamic_cast
base* pbase = new derived;
....
derived* pderived = dynamic_cast<derived*>(pbase);
if (derived) {
// do something
} else {
// error
}
To use the base class pointer, you must change the base class definition to be:
class base
{
public:
virtual void myFunc() { }
};
I see no other way around it. Sorry.
You could add it as a member of base and make it a virtual or pure virtual function. If using this route however, you should also add a virtual destructor in the base class to allow successful destruction of inherited objects.
class base
{
public:
virtual ~base(){};
virtual void myFunc() = 0;
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};