async call on override functions - c++

if i use the virtual function (*1) in the base class - the following code works as i inspected (print a_tmp and print b_tmp) but not if i use override function's (*2) (2x "print base" will be shown). What is the correct way to call the functions (async) in case of override functions?
#include <iostream>
#include <future>
#include <vector>
class base
{
public:
virtual void print() = 0; // *1
// void print() { std::cout << "print base" << std::endl; }; // *2
};
class a_tmp : public base
{
public:
void print() { std::cout << "print a_tmp" << std::endl; };
};
class b_tmp : public base
{
public:
void print() { std::cout << "print b_tmp" << std::endl; }
};
std::vector<std::future<void>> future_result;
int main()
{
a_tmp a_1_tmp;
b_tmp b_2_tmp;
base* ab_array[] = { &a_1_tmp,&b_2_tmp };
for (auto ptr : ab_array)
{
future_result.push_back(async(std::launch::async, &base::print ,ptr));
}
for (auto& e : future_result) {
e.get();
}
}

Related

Vector of shared pointers to templated classes

I have a templated class TaskRunner that takes a polymorphic type Task and I want to create a container of shared pointers to them.
class Task {
virtual void run() = 0;
};
class LoudTask : Task {
void run() {
std::cout << "RUNNING!" << std::endl;
}
};
class QuietTask : Task {
void run() {
std::cout << "running!" << std::endl;
}
};
template<typename T> class TaskRunner {
public:
TaskRunner<T>() {
task = std::make_unique<T>();
}
private:
std::unique_ptr<T> task;
};
using Runner = std::shared_ptr<TaskRunner<Task>>;
However I get error: no matching member function for call to 'push_back' with:
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());
Due to:
note: candidate function not viable: no known conversion from 'shared_ptr<TaskRunner>' to 'const shared_ptr<TaskRunner>' for 1st argument
Implemented IgorTandetnik's suggestion, and it works for me:
#include <iostream>
#include <memory>
#include <vector>
class Task {
virtual void run() = 0;
};
class LoudTask : Task {
public:
void run() {
std::cout << "RUNNING!" << std::endl;
}
};
class QuietTask : Task {
public:
void run() {
std::cout << "running!" << std::endl;
}
};
class TaskRunnerBase
{
public:
virtual void run() =0;
};
template <class T>
class TaskRunner: public TaskRunnerBase {
public:
TaskRunner():
task(std::make_unique<T>()) {
}
void run() override
{
task->run();
}
private:
std::unique_ptr<T> task;
};
int main()
{
using Runner = std::shared_ptr<TaskRunnerBase>;
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner<QuietTask>>());
runners.push_back(std::make_shared<TaskRunner<LoudTask>>());
runners[0]->run();
runners[1]->run();
}
Output:
running!
RUNNING!
Note however that TaskRunner doesn't need to be a template; as it is currently implemented above, it has a kind of double role: (1) task factory, and (2) container and runner of tasks.
paolo's answer separates this out nicely, there, the factory aspect is moved to the main function.
If TaskRunner is supposed to run tasks that inherit from Task only, you may consider de-templatizing it:
#include <iostream>
#include <memory>
#include <vector>
class Task {
public:
virtual void run() = 0;
};
class LoudTask : public Task {
public:
void run() override { std::cout << "RUNNING!" << std::endl; }
};
class QuietTask : public Task {
public:
void run() override { std::cout << "running!" << std::endl; }
};
class TaskRunner {
public:
explicit TaskRunner(std::unique_ptr<Task>&& task_)
: task(std::move(task_)) {}
void run() {
if (this->task) this->task->run();
}
private:
std::unique_ptr<Task> task;
};
int main() {
using Runner = std::shared_ptr<TaskRunner>;
std::vector<Runner> runners;
runners.push_back(
std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
runners.push_back(
std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));
for (auto& runner : runners) runner->run();
}
This is another implementation that eliminates the need for another inheritance hierarchy and vtable since we already accomplished that with the Task hierarchy:
#include <iostream>
#include <vector>
class Task {
public:
virtual void run() = 0;
};
class LoudTask : public Task {
public:
void run() {
std::cout << "RUNNING!" << std::endl;
}
};
class QuietTask : public Task {
public:
void run() {
std::cout << "running!" << std::endl;
}
};
class TaskRunner {
public:
TaskRunner(std::unique_ptr<LoudTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
TaskRunner(std::unique_ptr<QuietTask> task) : m_task{ std::unique_ptr<Task>(task.release()) } {}
void run()
{
m_task->run();
}
private:
std::unique_ptr<Task> m_task;
};
using Runner = std::shared_ptr<TaskRunner>;
int main()
{
std::vector<Runner> runners;
runners.push_back(std::make_shared<TaskRunner>(std::make_unique<QuietTask>()));
runners.push_back(std::make_shared<TaskRunner>(std::make_unique<LoudTask>()));
runners[0]->run();
runners[1]->run();
}

In latest C++ How can I make a Class with member function organized in groups and sub groups (as tree)?

I am trying to organize public member function in groups and sub groups. But I would like these functions to have access to all public and private members of the class. Here is a code that does the job, but it is ugly. I am looking for more elegant way of doing the same thing.
#include "iostream"
class tClass
{
public:
tClass()
{
this->Grp1.SubGrp1.me = this;
this->Grp1.SubGrp2.me = this;
this->Grp1.SubGrp3.me = this;
};
~tClass() {};
struct Grp1
{
struct SubGrp1
{
tClass* me;
void Fun1(void) { me->Group1_SubGroup1_Function1(); };
void Fun2(void) { me->Group1_SubGroup1_Function2(); };
void Fun3(void) { me->Group1_SubGroup1_Function3(); };
}SubGrp1;
struct SubGrp2
{
tClass* me;
void Fun1(void) { me->Group1_SubGroup2_Function1(); };
void Fun2(void) { me->Group1_SubGroup2_Function2(); };
}SubGrp2;
struct SubGrp3
{
tClass* me;
void Fun1(void) { me->Group1_SubGroup3_Function1(); };
}SubGrp3;
}Grp1;
private:
void Group1_SubGroup1_Function1(void) { std::cout << "Group1_SubGroup1_Function1\n"; };
void Group1_SubGroup1_Function2(void) { std::cout << "Group1_SubGroup1_Function2\n"; };
void Group1_SubGroup1_Function3(void) { std::cout << "Group1_SubGroup1_Function3\n"; };
void Group1_SubGroup2_Function1(void) { std::cout << "Group1_SubGroup2_Function1\n"; };
void Group1_SubGroup2_Function2(void) { std::cout << "Group1_SubGroup2_Function2\n"; };
void Group1_SubGroup3_Function1(void) { std::cout << "Group1_SubGroup3_Function1\n"; };
};
int main()
{
tClass aClass;
aClass.Grp1.SubGrp1.Fun1();
aClass.Grp1.SubGrp1.Fun2();
aClass.Grp1.SubGrp1.Fun3();
aClass.Grp1.SubGrp2.Fun1();
aClass.Grp1.SubGrp2.Fun2();
aClass.Grp1.SubGrp3.Fun1();
}
This is an IDE feature, not a C++ one.
For example visual studio allows for this (might not work in other environments). This allows you to group without impacting source code.
Bonus you can collapse groups to one line and expand them later.
#pragma region my_group_1
#pragma region sub_group_1
void func1();
#pragma endregion
#pragma region sub_group_2
void func2();
#pragma endregion
#pragma endregion
Mnd, this is how would organize your code example :
#include <iostream>
#include <string>
//------------------------------------------------------------------------------
// a base class to get all the constructors/destructors setup
// for an abstract base class ("interface")
struct interface_t
{
public:
interface_t(const interface_t&) = delete;
interface_t& operator=(const interface_t&) = delete;
interface_t(interface_t&&) = delete;
protected:
interface_t() = default;
virtual ~interface_t() = default;
};
//------------------------------------------------------------------------------
// now setup interfaces for all your groups
class group1_subgroup1_itf :
public interface_t
{
public:
virtual void fun1() = 0;
virtual void fun2() = 0;
};
class group1_subgroup2_itf :
public interface_t
{
public:
virtual void fun3() = 0;
virtual void fun4() = 0;
};
class group1_itf :
public interface_t
{
public:
virtual group1_subgroup1_itf& sub1() = 0;
virtual group1_subgroup2_itf& sub2() = 0;
};
class t_class_itf :
public interface_t
{
public:
virtual group1_itf& group1() = 0;
};
//------------------------------------------------------------------------------
// Then put your implementation all in one class, just like normal.
// let this class implement all the interfaces (groupings)
//
namespace impl
{
class t_class :
public t_class_itf,
public group1_itf,
public group1_subgroup1_itf,
public group1_subgroup2_itf
{
public:
explicit t_class(const std::string name) :
m_name{ name }
{
};
virtual ~t_class() override = default;
// todo other constructors
// implementation of navigation functions, they all end up in the same implementation.
virtual group1_itf& group1() override {return dynamic_cast<group1_itf&>(*this); }
virtual group1_subgroup1_itf& sub1() override { return dynamic_cast<group1_subgroup1_itf&>(*this); }
virtual group1_subgroup2_itf& sub2() override { return dynamic_cast<group1_subgroup2_itf&>(*this); }
// implementations
virtual void fun1() override { std::cout << m_name << "::fun1" << std::endl; }
virtual void fun2() override { std::cout << m_name << "::fun2" << std::endl; }
virtual void fun3() override { std::cout << m_name << "::fun3" << std::endl; }
virtual void fun4() override { std::cout << m_name << "::fun4" << std::endl; }
private:
std::string m_name;
};
} /* namespace impl */
//------------------------------------------------------------------------------
// client facing class
// used for "navigation" only
//
class t_class :
public t_class_itf
{
public:
explicit t_class(const std::string& name) :
m_impl{ name }
{
};
virtual group1_itf& group1() override { return dynamic_cast<group1_itf&>(m_impl); }
private:
impl::t_class m_impl;
};
//------------------------------------------------------------------------------
// and then its use.
int main()
{
t_class t{"t_class"};
t.group1().sub1().fun1();
t.group1().sub2().fun4();
return 0;
}
Thanks to all commends I got ideas how to decrease the complexity.
Here is simple solution and better example that exercises public/private access rights.
Memory Overhead: Extra pointer in each subgroup.
Code Overhead: Dynamic Initialization of all subgroup pointers.
#include "iostream"
class tClass
{
public:
tClass()
{
this->Grp1.SubGrp1.me = this;
this->Grp1.SubGrp2.me = this;
this->Grp1.SubGrp3.me = this;
};
~tClass() {};
struct Grp1
{
struct SubGrp1
{
tClass* me;
void Fun1(void) { me->aVar = 0x0101; me->mCount++; std::cout << "Group1_SubGroup1_Function1 Count=" << me->mCount << "\n"; };
void Fun2(void) { me->aVar = 0x0102; me->mCount++; std::cout << "Group1_SubGroup1_Function2 Count=" << me->mCount << "\n"; };
void Fun3(void) { me->aVar = 0x0103; me->mCount++; std::cout << "Group1_SubGroup1_Function3 Count=" << me->mCount << "\n"; };
}SubGrp1;
struct SubGrp2
{
tClass* me;
void Fun1(void) { me->aVar = 0x0201; me->mCount++; std::cout << "Group1_SubGroup2_Function1 Count=" << me->mCount << "\n"; };
void Fun2(void) { me->aVar = 0x0201; me->mCount++; std::cout << "Group1_SubGroup2_Function2 Count=" << me->mCount << "\n"; };
}SubGrp2;
struct SubGrp3
{
tClass* me;
void Fun1(void) { me->aVar = 0x0301; me->mCount++; std::cout << "Group1_SubGroup3_Function1 Count=" << me->mCount << "\n"; };
}SubGrp3;
}Grp1;
unsigned int aVar = 0x0000;
private:
int mCount = 0;
};
int main()
{
tClass aClass;
aClass.Grp1.SubGrp1.Fun1();
aClass.Grp1.SubGrp1.Fun2();
aClass.Grp1.SubGrp1.Fun3();
aClass.Grp1.SubGrp2.Fun1();
aClass.Grp1.SubGrp2.Fun2();
aClass.Grp1.SubGrp3.Fun1();
}

Best implementation for a class that can have different base member implementations

I would like to have a child class Handler that handles multiple callbacks and transfers data from one class to another. However, the base classes B1 and B2can have different implementations for its members.
Below a way to implement the behavior I want. I think there should be a better way but cannot figure it out.
// Example program
#include <iostream>
#include <string>
template <class T>
class IBase
{
public:
IBase()
{
object = new T(*this);
};
~IBase()
{
delete object;
}
virtual void ValidateCallback()
{
};
void RxCallback()
{
object->RxCallback();
};
void Send()
{
object->Send();
};
T* object;
};
class C1
{
public:
virtual void RxCompleteCallback() = 0;
void RxParse()
{
std::cout << "Parse C1" << std::endl;
RxCompleteCallback();
};
};
class C2
{
public:
virtual void RxCompleteCallback() = 0;
void RxParse()
{
std::cout << "Parse C2" << std::endl;
RxCompleteCallback();
};
};
class B1 : public C1
{
public:
B1(IBase<B1> &handler )
{
ihandler = &handler;
};
void DoSomething()
{
std::cout << "DoSomething B1" << std::endl;
ihandler->ValidateCallback();
};
void RxCompleteCallback() override
{
std::cout << "DoSomething other than B2" << std::endl;
std::cout << "RxCompleteCallback" << std::endl;
};
void RxCallback()
{
RxParse();
};
void Send()
{
DoSomething();
};
IBase<B1> * ihandler;
};
class B2 : public C2
{
public:
B2(IBase<B2> &handler )
{
ihandler = &handler;
};
void DoSomething()
{
std::cout << "DoSomething B2" << std::endl;
ihandler->ValidateCallback();
};
void RxCompleteCallback() override
{
std::cout << "DoSomething other than B1" << std::endl;
std::cout << "RxCompleteCallback" << std::endl;
};
void RxCallback()
{
RxParse();
};
void Send()
{
DoSomething();
};
IBase<B2> * ihandler;
};
class Validate
{
public:
void CalculateValidation()
{
std::cout << "Calculate validation" << std::endl;
};
};
template <class T>
class Handler : public IBase<T>, public Validate
{
public:
void ValidateCallback() override
{
std::cout << "ValidateCallback" << std::endl;
CalculateValidation();
};
void Receive()
{
IBase<T>::RxCallback();
};
void Send()
{
IBase<T>::Send();
}
};
int main()
{
Handler<B1> handler1;
handler1.Receive();
handler1.Send();
std::cout << std::endl;
Handler<B2> handler2;
handler2.Receive();
handler2.Send();
}
Output:
Parse C1
DoSomething other than B2
RxCompleteCallback
DoSomething B1
ValidateCallback
Calculate validation
Parse C2
DoSomething other than B1
RxCompleteCallback
DoSomething B2
ValidateCallback
Calculate validation
There are several ways to do this in C++. It's hard to say what the best way is, it depends on how you will use it, and the example you gave is too simple to recommend a specific way. Normally, I'd say you want to derive your protocol-specific classes from Handler, instead of the other way around, so you'd write:
class Handler {
public:
virtual void Receive() {};
virtual void Send() {};
};
class B1: public Handler {
virtual void Receive() {
...
}
virtual void Send() {
...
}
};
int main() {
B1 handler1;
handler1.Receive();
...
}
The main issue here is that you need to use virtual member functions here, otherwise the base class doesn't know which derived class's implementation to call. But it does allow you to pass a Handler * as an argument to another function, which will then work with any derived class without needing any templating.
Another option is to use the curiously recurring template pattern, which would look like:
template <typename T>
class Handler {
void Receive() {
static_cast<T*>(this)->Receive();
}
void Send() {
static_cast<T*>(this)->Send();
}
};
class B1: public Handler<B1>
{
void Receive() {
...
}
void Send() {
...
}
};
int main() {
B1 handler1;
handler1.Receive();
...
}
This avoids virtual methods.
It is also quite similar to your class Handler, but it has the advantage that it doesn't need the T *object member variable.

Virtual template function in c++

I have been looking for a way to use both templating and polymorphism at the same time. Here's a simplified version of my problem:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
//*******************************************************************
//*******************************************************************
struct DerivedStuff1
{
static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2
{
static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
template<typename StuffType> virtual void eval() const = 0;
};
class DerivedClass1 : public BaseClass
{
public:
template<typename StuffType> virtual void eval() const
{
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
};
class DerivedClass2 : public BaseClass
{
public:
template<typename StuffType> virtual void eval() const
{
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
BaseClass* c1 = new DerivedClass1;
c1->eval<DerivedStuff1>();
c1->eval<DerivedStuff2>();
BaseClass* c2 = new DerivedClass2;
c2->eval<DerivedStuff1>();
c2->eval<DerivedStuff2>();
return 0;
}
This code does not compile because virtual template functions are not allowed in C++. I found a few approaches to tackle this problem (CRTP, etc.) but none of them were really satisfying. Is there no elegant way to get around that issue?
The visitor pattern turns run-time polymorphism on its side and makes runtime-polymorphic function templates possible. It has other legitimate uses apart from templatisation, so I guess you can call it somewhat elegant.
Your example can look as follows:
#include <iostream>
class DerivedStuff1 {
public:
static void eval() { std::cout << "Evaluating DerivedStuff1\n"; }
};
class DerivedStuff2 {
public:
static void eval() { std::cout << "Evaluating DerivedStuff2\n"; }
};
class DerivedClass1; class DerivedClass2;
class BaseClassVisitor {
public:
virtual void visit(DerivedClass1&) = 0;
virtual void visit(DerivedClass2&) = 0;
};
class BaseClass {
public:
virtual void accept(BaseClassVisitor& v) = 0;
};
class DerivedClass1 : public BaseClass
{
public:
virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};
class DerivedClass2 : public BaseClass
{
public:
virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};
template <typename StuffType>
class EvalVisitor : public BaseClassVisitor
{
virtual void visit(DerivedClass1&) {
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
virtual void visit(DerivedClass2&) {
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
EvalVisitor<DerivedStuff1> e1;
EvalVisitor<DerivedStuff2> e2;
BaseClass* c1 = new DerivedClass1;
c1->accept(e1);
c1->accept(e2);
BaseClass* c2 = new DerivedClass2;
c2->accept(e1);
c2->accept(e2);
return 0;
}
Demo
Of course all shortcomings of Visitor apply here.
You could reinvent the vtable and resolve the function pointer at run time. You will, however, have to explicitely instantiate the template on the derived class, but I don't see any approach to this that won't require that.
Quick and dirty example:
#include <map>
#include <iostream>
class Base {
public:
typedef void (Base::*eval_ptr)();
using eval_vtable = std::map<std::type_index, eval_ptr>;
Base(eval_vtable const& eval_p) : eval_ptrs(eval_p) {}
template<typename T>
void eval() {
auto handler = eval_ptrs.find(type_index(typeid(T)));
if(handler != eval_ptrs.end()) {
auto handler_ptr = handler->second;
(this->*handler_ptr)();
}
}
eval_vtable const& eval_ptrs;
};
class Derived : public Base {
public:
Derived()
: Base(eval_functions) {}
template<typename T>
void eval_impl() {
std::cout << typeid(T).name() << "\n";
}
static eval_vtable eval_functions;
};
Base::eval_vtable Derived::eval_functions = {
{ type_index(typeid(int)), eval_ptr(&Derived::eval_impl<int>) },
{ type_index(typeid(float)), eval_ptr(&Derived::eval_impl<float>) },
{ type_index(typeid(short)), eval_ptr(&Derived::eval_impl<short>) },
};
int main(int argc, const char* argv[]) {
Derived x;
Base * x_as_base = &x;
x_as_base->eval<int>(); // calls Derived::eval_impl<int>()
return 0;
}
This won't be exactly fast, but it will give you the closest thing to templated virtual functions that I can think of.
Edit: For the record I don't advocate anyone use this. I would much rather revisit the design to avoid being painted in this particular corner in the first place. Please consider my answer as an academic solution to a theoretical problem, not an actual engineering recommendation.
Since virtual template methods in C++ arent allowed, you can make a class template and call static function of class template param.
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
//*******************************************************************
//*******************************************************************
struct DerivedStuff1
{
static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2
{
static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
virtual void eval() const = 0;
};
template<typename StuffType>
class DerivedClass1 : public BaseClass
{
public:
virtual void eval() const
{
std::cout << "We are in DerivedClass1: ";
StuffType::eval();
}
};
template<typename StuffType>
class DerivedClass2 : public BaseClass
{
public:
virtual void eval() const
{
std::cout << "We are in DerivedClass2: ";
StuffType::eval();
}
};
int main()
{
BaseClass* c1 = new DerivedClass1<DerivedStuff1>;
c1->eval();
c1 = new DerivedClass1<DerivedStuff2>;
c1->eval();
BaseClass* c2 = new DerivedClass2<DerivedStuff1>;
c2->eval();
c2 = new DerivedClass2<DerivedStuff2>;
c2->eval();
// deletes
return 0;
}
Output
We are in DerivedClass1: evaluating DerivedStuff1
We are in DerivedClass1: evaluating DerivedStuff2
We are in DerivedClass2: evaluating DerivedStuff1
We are in DerivedClass2: evaluating DerivedStuff2
You cannot mix templates (compile time) and polymorphic (runtime). That's it.
So, a posible workaround is remove templates. For example, it could take a function pointer or just more polymorphism:
//*******************************************************************
//*******************************************************************
struct InterfaceStuff{
virtual void eval() = 0;
}
struct DerivedStuff1 : public InterfaceStuff
{
void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2 : public InterfaceStuff
{
void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
virtual void eval(InterfaceStuff* interface) const = 0;
};
class DerivedClass1 : public BaseClass
{
public:
virtual void eval(InterfaceStuff* interface) const
{
std::cout << "We are in DerivedClass1: ";
interface->eval();
}
};
class DerivedClass2 : public BaseClass
{
public:
virtual void eval(InterfaceStuff* interface) const
{
std::cout << "We are in DerivedClass2: ";
interface->eval();
}
};
Another posible workaround is remove polymorphism, just use more templates:
struct DerivedStuff1
{
static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};
struct DerivedStuff2
{
static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};
//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
template<typename Eval,typename StuffType> void eval() const
{
Eval::eval();
StuffType::eval();
}
};
class DerivedClass1 : public BaseClass
{
};
class DerivedClass2 : public BaseClass
{
};
One way of another, you have to choose one.

Automatic method selection based on class instance

I have two variants of the same method. I also have an instance of a base class type, but I don't know what specific class it is an instance of. I now want to automatically select the appropriate method depending on the actual type of the object. It seems impossible though and the only solution I can come up with is to check all possibilities by casting.
There has to be a nicer solution though.
Here is my minimal example:
// Example program
#include <iostream>
#include <string>
#include <memory>
class A
{
public:
virtual void bar() const = 0;
};
class B : public A
{
public:
void bar() const
{
std::cout << "B.bar()" << std::endl;
}
};
class C : public A
{
public:
void bar() const
{
std::cout << "C.bar()" << std::endl;
}
};
class Z
{
public:
Z(int variable) : m_variable(variable) {};
void foo(std::shared_ptr<B> b)
{
std::cout << "Calling foo(B) method! " << m_variable << std::endl;
b->bar();
}
void foo(std::shared_ptr<C> c)
{
std::cout << "Calling foo(C) method!" << m_variable << std::endl;
c->bar();
}
private:
int m_variable;
};
int main()
{
std::shared_ptr<A> b(new B());
Z z(42);
//z.foo(b); // This doesn't work
// But this does
std::shared_ptr<B> b_cast = std::dynamic_pointer_cast<B>(b);
if (b_cast.get())
z.foo(b_cast);
}
http://cpp.sh/9fqne
At the moment I have to resort to dynamic_pointer_cast, but I find it kinda ugly and not very maintainable.
I also don't want to add the functionality of foo() to the classes B and C, because those are small independent data structures on which many other classes operate.
Thank you very much!
EDIT: In the original post I simplified a bit too much. The new example should clear things up.
Add a pure virtual function foo() to your base class and override in subsequent derived classes. Then have your global function foo() (which has nothing to do with member functions with the same name) accept a reference to std::shared_ptr const as a parameter:
#include <iostream>
#include <memory>
class A{
public:
virtual void foo() = 0;
};
class B : public A{
public:
void foo() override{
std::cout << "Calling foo(B) method!" << std::endl;
}
};
class C : public A{
public:
void foo() override{
std::cout << "Calling foo(C) method!" << std::endl;
}
};
void foo(const std::shared_ptr<A>& param){
param->foo();
}
int main(){
std::shared_ptr<A> b = std::make_shared<B>();
std::shared_ptr<A> c = std::make_shared<C>();
foo(b);
foo(c);
}
As BoBTFish pointed out, the visitor pattern is a potential solution for this problem:
// Example program
#include <iostream>
#include <string>
#include <memory>
class B;
class C;
class Visitor
{
public:
virtual void visit(B* b) const = 0;
virtual void visit(C* b) const = 0;
};
class A
{
public:
virtual void bar() const = 0;
virtual void accept(const Visitor* visitor) = 0;
};
class B : public A
{
public:
void bar() const
{
std::cout << "B.bar()" << std::endl;
}
void accept(const Visitor* visitor)
{
visitor->visit(this);
}
};
class C : public A
{
public:
void bar() const
{
std::cout << "C.bar()" << std::endl;
}
void accept(const Visitor* visitor)
{
visitor->visit(this);
}
};
class Z : public Visitor
{
public:
Z(int variable) : m_variable(variable) {};
void visit(B* b) const
{
std::cout << "Calling foo(B) method! " << m_variable << std::endl;
b->bar();
}
void visit(C* c) const
{
std::cout << "Calling foo(C) method!" << m_variable << std::endl;
c->bar();
}
private:
int m_variable;
};
int main()
{
std::shared_ptr<A> b(new B());
Z z(42);
b->accept(&z);
}
http://cpp.sh/2vah5
Thank you very much!