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.
Related
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;
}
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.
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!
I am deriving an object from two parent classes. These two parents each have different types of properties, but I want the child to keep them in sync with each other. However, I want to disallow users of the library from treating Child like a ParentA or a ParentB accidentally via slicing. For example:
#include <iostream>
class ParentA
{
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class ParentB
{
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class Child : public ParentA, public ParentB
{
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
ParentA::modify();
ParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
This call to Change(child); calls ParentA's modify() function, in which the ParentA properties can get out of sync with the ParentB properties, leaving the Child in a bad state.
There are many functions (the read*() ones here) in ParentA and ParentB that I don't want to have to manually forward from Child, so I can't derive privately.
Is there a way to make this call to Change(child) produce a compiler error (without changing the signature of Change)?
There is in fact a way to do this (although said you didn't like it): private or protected inheritance is the C++ mechanism to achieve what you want.
Bear in mind that since your child class is trying to keep some sort of invariant between A and B, if you inherit publicly, someone will find a way to use A or B's interface to violate the invariant anyway so you need to protect against those being used in the child directly, which the restricted inheritance does perfectly.
If there are then some methods in the parent that don't affect the two-class invariant you can using those down into the public section of Child.
As the comments already say the cleanest way might be to just inherit from ParentA and ParentB with private and forward the needed functions.
I had another idea: You could extract the functionality of ParentA and ParentB into 2 abstract classes (AbstractParentA,AbstractParentB) and use these classes as base classes.
This would give you the desired behaviour:
#include <iostream>
class AbstractParentA
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyA" << std::endl;
}
void readA()
{
std::cout << "readA" << std::endl;
}
};
class AbstractParentB
{
virtual void no_instance() = 0;
public:
void modify()
{
std::cout << "modifyB" << std::endl;
}
void readB()
{
std::cout << "readB" << std::endl;
}
};
class ParentA : public AbstractParentA
{
virtual void no_instance() override {}
};
class ParentB : public AbstractParentB
{
virtual void no_instance() override {}
};
class Child : public AbstractParentA, public AbstractParentB
{
virtual void no_instance() override {}
public:
void modify()
{
// Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
AbstractParentA::modify();
AbstractParentB::modify();
std::cout << "modifyChild" << std::endl;
}
};
void Change(ParentA object)
{
object.modify();
}
int main()
{
std::cout << "This is standard:" << std::endl;
ParentA parentA;
parentA.modify();
ParentB parentB;
parentB.modify();
Child child;
child.readA();
child.readB();
child.modify();
std::cout << "Want to avoid this:" << std::endl;
Change(child);
return 0;
}
error C2664: 'void Change(ParentA)': cannot convert argument 1 from 'Child'
note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
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.