I was reading about delegation and I wanted to able to call with a base class a any function pass as parameter depending on the event, I did it this way and it works but I am not sure if it is the proper way and if it is portable like this.
class base {
public:
typedef void (base::*methodPTR)();
methodPTR pfn;
void setMethod(methodPTR fn)
{
pfn = fn;
}
void run(){
if(pfn) (this->*pfn)();
}
};
class a : public base {
public:
void fn()
{
cout<<"from class a!"<<endl;
}
};
class b : public base
{
a ob;
public:
void init()
{
ob.setMethod(static_cast<base::methodPTR>(&b::fn));
}
void fn()
{
cout << "from class b!" << endl;
}
void test()
{
ob.run();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
b x;
x.init();
x.test();
return 0;
}
You are calling the member function fn of class b with an instance of class a which will cause undefineded behaviour if you access data memebers of your class.
Replace your classes a and b with this to see the magic :
class a : public base {
int j;
public:
a()
{
j = 42;
}
void fn()
{
cout<<"from class a!"<<endl;
}
};
class b : public base
{
int i;
a ob;
public:
void init()
{
i = 5;
ob.setMethod(static_cast<base::methodPTR>(&b::fn));
}
void fn()
{
cout << "from class b!" << endl;
cout << "i = " << i << endl;
}
void test()
{
ob.run();
}
};
Related
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();
}
#include<iostream>
using namespace std;
class base
{
public: void getdata()
{
cout<<"in base"<<endl;
}
};
class derived:public base
{
public: void getdata()
{
cout<<"in derived"<<endl;
}
void base:: getdata()
};
int main()
{
derived d;
d.getdata();
return 0;
}
I'm getting error: "cannot declare member function 'base::getdata' within 'derived'"
I want to print the content of both functions from derived class objects
#include<iostream>
using namespace std;
class base
{
public:
base() {
}
void getData()
{
cout << "in base" << endl;
}
};
class derived :public base
{
public:
derived(base b) {
b.getData();
}
void getdata()
{
cout << "in derived" << endl;
}
};
int main()
{
base b;
derived d(b);
d.getdata();
return 0;
}
try this.
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.
Is it possible to do such things in C++14. I have a base class as follows:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
class ConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //1
}
};
class SuperConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //2
}
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
As you can see at //1 and //2, the function's body is completely similar. But I can't quite move it into a base class because of depending on the static type of this. In spite of that fact, I wouldn't like to write absolutely the same code every time I need to add one more subclass of AbstractElement. So, I need some kind of mechanism which provides us with the facility to inject code into a function.
As long as marcos are not very desirable solution, I'd like to ask about some tricks that can be done in C++14 for solving such a problem.
Yes, it is possible using CRTP:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
template <class T>
class CRTPAbstractElement : public AbstractElement
{
B _b;
public:
virtual void foo()
{
T* t = dynamic_cast<T *>(this);
_b.bar(t);
}
};
class ConcreteElement : public CRTPAbstractElement<ConcreteElement>
{
};
class SuperConcreteElement : public CRTPAbstractElement<SuperConcreteElement>
{
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
By adding an intermediate CRTP class we are able to cast a pointer to the base class to a pointer to the derived class. Thus solving the issue of code duplication.
When a class inherits another publicly, then shouldn't all virtual functions get rewritten?
Consider the code --
class A {
private:
vector<int> v;
public
virtual int something() {
cout << "A" << endl;
return v.size();
}
}
class B : public A {
private:
priority_queue<int> v;
public
int something() {
cout << "B" << endl;
return v.size();
}
}
Now, when I call the function something() on an object b of class B by executing the statement b.something(), I get the output A. Why is this?
Corrected the errors (see http://codepad.org/ssivYhWb)
i.e.
#include <iostream.h>
class A {
private:
vector<int> v;
public:
virtual int something() {
cout << "A" << endl;
return v.size();
}
};
class B : public A {
private:
priority_queue<int> v;
public:
int something() {
cout << "B" << endl;
return v.size();
}
};
int main() {
B b;
b.something();
return 0;
}
It returns B - as expected