I would like to create a base class ==> derived class setup where the base class' constructor has a callback to run a (possibly complex) function to modify the base class' private member with information from the derived class. However, I'm running into a chicken and an egg problem because the base class constructor runs before the derived class' members are initialized. Here's the code to demonstrate the problem:
#include <iostream>
#include <functional>
class B
{
public:
typedef std::function<void(std::string &)> mod_func_t;
B(const mod_func_t &m) : foo("base str")
{
std::cout << "Base constructor\n";
m(foo);
std::cout << "base constructor finally has: " << foo << std::endl;
}
private:
std::string foo;
};
class D : public B
{
public:
D(const std::string &input) :
B(std::bind(&D::my_f, this, std::placeholders::_1)),
input_(input)
{
std::cout << "Derived constructor\n";
}
private:
void my_f(std::string &s)
{
std::cout << "Derived class' modification function\n";
s += input_; // <== Crashes here because input_ is not yet constructed
}
const std::string input_;
};
int main()
{
D d("my input");
return 0;
}
What is the correct way to do this?
One approach is to let D calculate the adjusted string before calling the constructor of B.
class D : public B {
D(std::string str)
: B(my_f(str))
{}
std::string my_f(std::string str) { return str + "..."; }
};
A second approach is to let the body of constructor D do some work. Here adjust_base could also be virtual.
class D : public B {
D(std::string str)
: B(str)
{
adjust_base();
}
void adjust_base();
};
I believe that CRTP could help you with this one..
There is a simple example:
#include <iostream>
#include <functional>
template <typename Derived>
class B
{
public:
B() : foo("base str")
{
static_cast<Derived*>(this)->m(foo);
std::cout << "Base constructor\n";
std::cout << "base constructor finally has: " << foo << std::endl;
}
void m(std::string& str) { //... }
private:
std::string foo;
friend Derived;
};
class D : public B<D>
{
public:
D(std::string &input) :
B(),
input_(input)
{
std::cout << "Derived constructor\n";
}
void m(const std::string& str) { //... }
private:
void my_f(std::string &s)
{
std::cout << "Derived class' modification function\n";
s += input_; // <== Crashes here because input_ is not yet constructed
}
const std::string input_;
};
int main()
{
D d("my input");
return 0;
}
Related
I have a abstract class named Base from which I derived a class(Derived) as follows:
#include <iostream>
#include <string>
#include <memory>
class Base
{
public:
virtual void printClass()const = 0;
virtual ~Base(){}
};
class Derived: public Base
{
private:
int m_var1;
std::string m_var2;
public:
Derived() = default;
Derived(const int& v1, const std::string& v2)
:m_var1(v1), m_var2(v2)
{ }
void printClass()const override
{
std::cout << "Derived Class with\t";
std::cout << m_var1 << " " << m_var2 << std::endl;
}
~Derived(){ std::cout << "Derived destroyed" << std::endl; }
};
Now in the main() to make use of polymorphisum I could declare as follows:
int main()
{
std::shared_ptr<Base> Obj[3];
Obj[0] = std::make_shared<Derived>(1,"One");
Obj[1] = std::make_shared<Derived>(2,"Two");
Obj[2] = std::make_shared<Derived>(3,"Three");
for(const auto& it: Obj)
it->printClass();
return 0;
}
However, I am currently trying to learn more about the std::shared_ptr<>() and its custom deletion technics and I came across following statement.
std::shared_ptr<Base> Obj(new Derived[3], [](Derived* obj){ delete[] obj; });
and
std::shared_ptr<Base> Obj(new Derived[3] = {
{1,"One"},
{2,"Two"},
{3,"Three"}
},
[](Derived* obj){ delete[] obj; });
My questions are:
Why I can not initialize or pass values to the constructor of Derived class in following manner, even-though I have a costume defined constructor available for the derived class? or am I missing something?
If so what would be the correct way of initializing and accessing
such array of derived class elements?
You can call the constructor like this:
std::shared_ptr<Base> Obj{
new Derived[3]{ {1,"One"}, {2,"Two"}, {3,"Three"} },
[](Derived* obj){ delete[] obj; }
};
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!
If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.
Please consider the following piece of code:
#include <iostream>
#include <string>
enum Type { T1, T2 };
class Base {
public:
std::string baseName;
Type type;
Base(const std::string& bn, Type t):
baseName(bn), type(t) {}
};
class Derived1 : public Base
{
public:
std::string dName;
int x = 10;
Derived1(const std::string& bn, const std::string& dn):
Base(bn, Type::T1), dName("Dervied1"+dn) {}
int getX(void) const { return x; }
};
class Derived2 : public Base
{
public:
std::string dName;
int y = 20;
Derived2(const std::string& bn, const std::string& dn):
Base(bn, Type::T2), dName("Derived2"+dn){}
int getY(void) const { return y; }
};
void func(Base& b)
{
if (b.type == Type::T1)
{
Derived1& d1 = static_cast<Derived1&>(b);
std::cout << d1.baseName << " " << d1.dName << " " << d1.getX();
std::cout << std::endl;
}
else
{
Derived2& d2 = static_cast<Derived2&>(b);
std::cout << d2.baseName << " " << d2.dName << " " << d2.getY();
}
};
int main(void)
{
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
The requirement is to have a function that can take in the base class value and then depending on the "type" of the derived instance, do something different. My question is - is this the right way of doing things or am I missing some important design pattern. I remember reading that use of static_cast or dynamic_cast means that there is something inherently wrong with the design. I understand that ideally the base class can have virtual functions that the derived classes implement, and at run time they get polymorphically dispatched. However, in this case there are two functions in each derived class that are specific to those classes, viz. getX and getY. How can I change the design to make it better and perhaps not use the cast?
Thanks!
The requirement is to have a function that can take in the base class value and then depending on the "type" of the derived instance, do something different.
That is exactly what polymorphism is all about. But you are not using it the way it is meant to be used.
My question is - is this the right way of doing things
No.
am I missing some important design pattern.
This would be better handled by getting rid of Type altogether and introduce a virtual method in Base.
I understand that ideally the base class can have virtual functions that the derived classes implement, and at run time they get polymorphically dispatched.
Exactly.
However, in this case there are two functions in each derived class that are specific to those classes, viz. getX and getY.
So? Using polymorphism correctly does not prevent that.
How can I change the design to make it better and perhaps not use the cast?
Use polymorphism correctly. For example:
#include <iostream>
#include <string>
class Base
{
public:
std::string baseName;
Base(const std::string& bn):
baseName(bn) {}
virtual void doIt() = 0;
};
class Derived1 : public Base
{
public:
std::string dName;
int x = 10;
Derived1(const std::string& bn, const std::string& dn):
Base(bn), dName("Dervied1"+dn) {}
int getX(void) const { return x; }
void doIt() override
{
std::cout << baseName << " " << dName << " " << getX();
std::cout << std::endl;
}
};
class Derived2 : public Base
{
public:
std::string dName;
int y = 20;
Derived2(const std::string& bn, const std::string& dn):
Base(bn), dName("Derived2"+dn) {}
int getY(void) const { return y; }
void doIt() override
{
std::cout << baseName << " " << dName << " " << getY();
}
};
void func(Base& b)
{
b.doIt();
}
int main(void)
{
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
And then take it a step farther by moving common code around so it can be shared by the derived classes:
#include <iostream>
#include <string>
class Base
{
public:
std::string baseName;
Base(const std::string& bn):
baseName(bn) {}
virtual void doIt()
{
std::cout << baseName;
}
};
class Derived : public Base
{
public:
std::string dName;
Derived(const std::string& bn, const std::string& dn):
Base(bn), dName(dn) {}
void doIt() override
{
Base::doIt();
std::cout << " " << dName;
}
};
class Derived1 : public Derived
{
public:
int x = 10;
Derived1(const std::string& bn, const std::string& dn):
Derived(bn, "Dervied1"+dn) {}
int getX(void) const { return x; }
void doIt() override
{
Derived::doIt();
std::cout << " " << getX();
std::cout << std::endl;
}
};
class Derived2 : public Derived
{
public:
int y = 20;
Derived2(const std::string& bn, const std::string& dn):
Derived(bn, "Derived2"+dn) {}
int getY(void) const { return y; }
void doIt() override
{
Derived::doIt();
std::cout << " " << getY();
}
};
void func(Base& b)
{
b.doIt();
}
int main(void)
{
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
If you have the option of using a virtual member function, as outlined by the other answer, it is the best approach to use. However, there are situations where you don't have that luxury. In that case, you can build your dispatch mechanism based on the type of the derived type.
#include <iostream>
#include <string>
#include <map>
class Base {
public:
std::string baseName;
Base(const std::string& bn): baseName(bn) {}
virtual ~Base() {}
// Don't store type ID per instance.
// Make it a virtual function so derived classes
// can return the same value for each instance.
virtual int getTypeID() = 0;
// Helper function for derived classes to use so each
// derived class can have a unique type id associated
// with it. This eliminates the need for having an enum.
static int getNextTypeID();
{
static int typeID = 0;
return ++typeID;
}
};
class Derived1 : public Base
{
public:
std::string dName;
int x = 10;
Derived1(const std::string& bn,
const std::string& dn):
Base(bn), dName("Dervied1"+dn) {}
// get type ID for this class.
// Every instance of the class will return
// same value.
virtual int getTypeID()
{
return getTypeIDStatic();
}
// This is a crucial piece of function
// that allows type based dispatch mechanism to work.
static int getTypeIDStatic()
{
static int typeID = Base::getNextTypeID();
return typeID;
}
int getX(void) const { return x; }
};
class Derived2 : public Base
{
public:
std::string dName;
int y = 20;
Derived2(const std::string& bn,
const std::string& dn):
Base(bn), dName("Derived2"+dn){}
int getY(void) const { return y; }
virtual int getTypeID()
{
return getTypeIDStatic();
}
static int getTypeIDStatic()
{
static int typeID = Base::getNextTypeID();
return typeID;
}
};
// Define a function type.
using Function = void (*)(Base& b);
// Keep a registry of functions that can be called for
// different types derived from Base.
std::map<int, Function>& getRegisteredFunctionsMap()
{
static std::map<int, Function> functionsMap;
return functionsMap;
}
// Provide a mechanism to register functions for types
// derived from Base.
template <typename T>
void registerFunction(Function f)
{
getRegisteredFunctionsMap()[T::getTypeIDStatic()] = f;
}
void func(Base& b)
{
// Check whether there is a function base on the type of b.
std::map<int, Function>& functionsMap = getRegisteredFunctionsMap();
std::map<int, Function>::iterator iter = functionsMap.find(b.getTypeID());
if ( iter != functionsMap.end() )
{
// If yes, call it.
iter->second(b);
}
else
{
// No function to deal with the type.
// Deal with the situation.
}
};
// A function that can be called when the real type is Derived1.
void derived1Fun(Base& b)
{
// Assume that b is derived.
Derived1& d1 = dynamic_cast<Derived1&>(b);
// Now use d1.
std::cout << d1.baseName << " " << d1.dName << " " << d1.getX();
std::cout << std::endl;
}
// A function that can be called when the real type is Derived2.
void derived2Fun(Base& b)
{
// Assume that b is Derived2.
Derived2& d2 = dynamic_cast<Derived2&>(b);
// Now use d2.
std::cout << d2.baseName << " " << d2.dName << " " << d2.getY();
std::cout << std::endl;
}
int main(void)
{
// Register functions for Derived1 and Derived2.
registerFunction<Derived1>(derived1Fun);
registerFunction<Derived2>(derived2Fun);
// Make the function calls.
Derived1 d1("Base", "foo");
func(d1);
Derived2 d2("Base", "foo");
func(d2);
}
Output of running the above program:
Base Dervied1foo 10
Base Derived2foo 20
#include <iostream>
using namespace std;
class Base
{
public:
void who()
{
cout << "I am " << _name << endl;
}
protected:
std::string _name;
};
class A : public Base
{
public:
A()
{
_name = "A class";
}
};
class B : public Base
{
public:
B()
{
_name = "B class";
}
};
class Wrapper
{
public:
Wrapper(Base *i):_data(i)
{
}
operator A()
{
A a;
// dynamic_cast<A*>(_data);
return a;
}
operator B()
{
B a;
// dynamic_cast<B*>(_data);
return a;
}
private:
Base* _data;
};
void madeForClass(A iObject)
{
cout << "call madeForClass A";
}
void madeForClass(B iObject)
{
cout << "call madeForClass B";
}
int main()
{
A a;
Base* b = &a;
madeForClass(Wrapper(b));
return 0;
}
when I execute this, I get error from compile saying:
error: call of overloaded 'madeForClass(Wrapper)' is ambiguous
I understand that it cannot deduce right function even though i have overloaded the typecast. But, How can I achieve such dynamism?
For more info, I somehow want to use the dynamic_cast in the overloading function or somewhere in such a way that based on the outcome of cast it should choose the corresponding madeForClass function.
For the given example, the cast will fail for 'B' hence should call madeForClass(A i);
As alternative, you may do
class Wrapper
{
public:
Wrapper(Base *i) : _data(i) {}
template <typename F>
auto Apply(F f)
{
if (auto a = dynamic_cast<A*>(_data)) {
f(*a);
} else if (auto b = dynamic_cast<B*>(_data)){
f(*b);
}
}
private:
Base* _data;
};
And then
Wrapper(base).Apply([](const auto& e){ madeForClass(e); });
Demo
or use Visitor instead of manual dynamic_cast