I am playing around with the Visitor pattern, and I have the following bit of code which compiles:
class DerivedVisitee;
class Visitor
{
public:
void visit(DerivedVisitee &v);
};
class Visitee
{
public:
virtual void accept(Visitor &v) = 0;
};
class DerivedVisitee : public Visitee
{
public:
void accept(Visitor &v) { v.visit(*this); }
};
I would like to provide a default visit method for all descendants of Visitee. As such, I tried to do the following:
class DerivedVisitee;
class Visitor
{
public:
void visit(DerivedVisitee &v);
};
class Visitee
{
public:
virtual void accept(Visitor &v) { v.visit(*this); } // added implementation here
};
class DerivedVisitee : public Visitee
{
// removed overridden method
};
But compilation fails with 'void Visitor::visit(DerivedVisitee &)' : cannot convert argument 1 from 'Visitee' to 'DerivedVisitee &' (MSVC). Can you explain why this happens, and what is a correct method for doing what I'm trying to do?
EDIT: Visitor::visit needs to work on DerivedVisitee objects only; to put it another way, I intend to use multiple overloaded Visitor::visit methods with different implementations, for different descendants of Visitee.
The basic answer is: you cannot in pure object oriented code.
By nature the Visitor pattern is about passing to visit the derived type, and in Visitee said type is unknown (it's a runtime property).
In C++, there exists a pattern called CRTP:
template <typename Derived, typename Base>
class VisiteeHelper: public Base {
public:
virtual void accept(Visitor& v) override {
Derived& d = static_cast<Derived&>(*this);
v.visit(d);
}; // class VisiteeHelper
and then you can derive from this:
// And there we see the "Curiously Recurring" part:
class DerivedVisitee: public VisiteeHelper<DerivedVisitee, Visitee> {
}; // class DerivedVisitee
class MoreDerivedVisitee: public VisiteeHelper<MoreDerivedVisitee, DerivedVisitee> {
}; // MoreDerivedVisitee
It's up to you to decide whether you prefer the dead-simple boilerplate or the smart (but potentially confusing) CRTP solution.
Personally, unless you have multiple overloads of accept (up to 4 per type by overloading on const-ness), I would not bother. It's about as much work to write the accept by hand, and it's dead simple, and immediately understandable.
You should pass Visitee& instead of DerivedVisitee& as argument of visit method. This is the whole point of using public inheritance and Polymorphism. Any derived object can be used where a base object is expected. At runtime, the actual type will be deducted and appropriate method will be called on that object.
Related
I'm still figuring out C++, and I have not been able to put this together from searching on google. I'm working with a larger project used by other people and I'm trying to expand the functionality of a class without breaking anyone else's code. In particular there is an untouchable Base class and Derived class that both implement a "crunch numbers" method that works on std::vector.
class Base {
public:
void crunch_numbers(std::vector& v) { // do stuff to v; }
};
class Derived : public Base {
public:
void crunch_numbers(std::vector& v) override { // do different stuff to v; }
};
I'm working with Eigen::Vector, and I was hoping to get away with something like this:
template <typename vec>
class MyDerived : public Base {
public:
void crunch_numbers(vec& v) override { // do different stuff to v; }
};
typedef MyDerived<std::vector> Derived;
That would let me work with different vectors and wouldn't break any existing code that uses the Derived class. But, when compiling my code, I get the error error: ‘void MyDerived<vec>::crunch_numbers(vec) [with vec = Eigen::Matrix<double, 2, 1>]’ marked ‘override’, but does not override. ... Because Base class only operates on std::vector.
I can't touch Base class because there may be other derived classes I don't know about. I'd like to have the flexibility to work with different vector types in the future without just adding overloads to Derived class. Is there a way to do this?
Issue is that override is correct only for one instantiation.
and we don't have conditional override (as we have for noexcept)
The simplest is to drop completely override:
template <typename vec>
class MyDerived : public Base {
public:
void crunch_numbers(vec& v) { /* do different stuff to v; */ }
};
So regular cases works,
but the true override case is not checked.
Else you can use specialization... but you would have some duplication just to add override in a specific case.
I'm not exactly sure what to call this inheritance scheme, but I'm trying to use a cloneable interface with a default implementation. I'm having some issues getting the correct scheme though.
I'm basing this somewhat on the cloneable interface defined in C#.
First I have my interface and default implementations:
template<class BaseType>
class ICloneable
{
public:
virtual std::shared_ptr<BaseType> Clone() const = 0;
};
template<class BaseType, class DerivedType>
class Cloneable : public ICloneable<BaseType>
{
public:
virtual std::shared_ptr<BaseType> Clone() const
{
return std::shared_ptr<BaseType>(new DerivedType(*(DerivedType*)this));
}
};
My desire is to have the following scheme.
// A pure virtual base interface
class Base : public ICloneable<Base>
{
public:
virtual void SomeFunc() = 0;
}
// Another implementation
class Imp1 : public Base, Cloneable<Base, Imp1>
{
public:
virtual void SomeFunc() {}
}
// An implementation
class Imp2 : public Cloneable<Base, Imp2>
{
public:
virtual void SomeFunc() {}
}
If I have a list of `std::shared_ptr' objects, I can invoke the Clone function when I want to make a deep copy without having to manually write the function in every one of the implementations.
Right now I get that Imp is an abstract class, which doesn't surprise me. Anyone know how I can get this default implementation idea to work? The point is to not have to manually write the clone function for every one of the implementations. It might not be doable but I'm out of ideas to try.
You could do the following:
#include <memory>
template<typename InterfaceType_>
struct ICloneable
{
using InterfaceType = InterfaceType_;
virtual ~ICloneable() = default;
virtual std::shared_ptr<InterfaceType> clone() const = 0;
};
template<typename T, typename Base = ICloneable<T>>
struct CloneableMixin : public Base
{
using InterfaceType = typename Base::InterfaceType;
// With the following line uncommented, code does not compile in MSVC
//using typename Base::InterfaceType;
std::shared_ptr<InterfaceType> clone() const override
{ return std::make_shared<T>(*static_cast<const T*>(this)); }
};
Now, this can be used as follows:
struct SomeBaseClass : public CloneableMixin<SomeBaseClass> { /*...*/ };
struct SomeDerivedClass : public CloneableMixin<SomeDerivedClass, SomeBaseClass> { /*...*/ };
Two notes:
In order to be able to access InterfaceType_ template parameter of ICloneable, you need to make it a template alias, and then use using typename Base::InterfaceType (as it is template parameter dependent type).
I've provided default type for Base template parameter of CloneableMixin - this allows to use it for base classes, for which you want to have clone implemented.
Moreover, two unrelated comments:
You don't need to type virtual - it's implied. It's a good idea to add override at the end (this makes sure that the method actually overrides something, otherwise a compiler will report an error).
You might consider using std::make_shared instead of new.
I usually try to find answers here before I post anything, but I'm not even sure how to formulate my question.
So here's what I want to do... I want to define a Base Interface, and a Derived Interface. Then, I want to implement the Base Interface, with extra variables and methods. Finally, I want to implemented a Derived class, from the implemented Base Interface BUT ALSO from the Derived Interface. I don't know about you, but my head hurts.
If I do something like below, I get Ambiguous definitions under the DerivedFloat code since that code "sees" both the GetBaseValue method from the IBase, inherited through IDerivedFloat, as well as the GetBaseValue inherited from Base.
Surely, there must be a way to derive a class which uses the expanded features of the Base Implementation, as well as making sure it implements the required IDerivedFloat methods.
Now... This is a dummy example to show what I'm conceptually trying to achieve. It's not a real life example.
template <typename VALUE_TYPE>
class IBase
{
public:
virtual VALUE_TYPE GetBaseValue() const = 0;
};
class IDerivedFloat : public IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
// Implementation of Base
template <typename VALUE_TYPE>
class Base : public IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
// Uses expanded Base AND implements IDerivedFloat
class DerivedFloat : public Base<FLOAT>, public IDerivedFloat
{
public:
void SetBaseValue(const FLOAT & value) { m_BaseValue = value };
}
You can use virtual inheritance to work around this problem:
class IDerivedFloat : virtual IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
template <typename VALUE_TYPE>
class Base : virtual IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
Using virtual inheritance gives the derive class one instance of the base class members, instead of one from each time it exists in the class hierarchy.
Multiple inheritance is an issue precisely because of the ambiguity issue you ran into, but there are ways to get around it. You have to explicitly tell the compiler which super you are calling the ambiguous functions from, by leading the function call with the super's name and a double colon.
Example:
- C inherits from A and B.
- A and B both have add() function.
- In C, you have to say A::add() or B::add() to tell the compiler which one to use.
Link for details and more complete implementation: http://www.cprogramming.com/tutorial/multiple_inheritance.html
I have the following structure
class Base
{
public:
Base(Type);
virtual render
}
class A
{
public:
Base(Type == A);
void render()
}
class B
{
public:
Base(Type == B);
void render()
}
void client_function()
{
Base baseObject(A);
//Base is an instance of class A
baseObject.render()//runs class A render
}
There are things in the above code that are not c++ as far as I am aware, they are closely related to pattern matching found in Haskell for example, but this is the best way I could find to illustrate my question without already knowing the answer ;)
In writing I want the client to be able to create a base object and pass the type of object as an argument, the correct specification of the object is returned and the client need not care less about it, just knows that running render will run the correct specific render.
Please feel free to ask questions if I have been unclear :)
I think you need to read about virtual functions and inheritance:
http://www.parashift.com/c++-faq-lite/virtual-functions.html
http://www.parashift.com/c++-faq-lite/proper-inheritance.html
http://www.parashift.com/c++-faq-lite/abcs.html
You need run-time polymorphism. There is not much important part of constructor. You have to inherit the Base into A and B. For example:
class Base
{
public:
virtual void render (); // <--- declare 'virtual'
virtual ~Base(); // <--- very much needed to avoid undefined behavior
};
class A : public Base //<---- inheritance
{
public:
void render(); // <--- this also becomes 'virtual'
};
...
Now you can use as per your requirement.
Base *baseObject = new A(); // <----- need to use pointer (or reference)
(*baseObject).render(); // <--- other way to write: baseObject->render();
delete baseObject;
I'm not sure I understood your question. In C++ you cannot choose your base class at runtime, but you certainly can have your base class depend from the derived class. This is done by using templates and what is known as the Curiously Recurring Template Pattern:
template <typename T> class Base {
public:
virtual void render(T *) {}
};
class A : public Base<A>
{
public:
void render(A * t) {}
};
class B : public Base<B>
{
public:
void render(B * t) {}
};
void client_function() {
A a1;
A a2;
a1.render(&a2); // calls A::render
a1.Base<A>::render(&a2); // calls Base<A>::render
Base<A> * ba = &a1;
ba->render(&a2); // calls A::render
}
Hope this answers your question.
What you ask for is exactly what inheritance is for: creating object from a class hierarchy that specializes a functionality.
In your example, apart from syntax problems, things will work as you expect, i.e. method A::render will be called, even if you don't know at compile time that object, declared as a Base, is indeed a A. That's virtual inheritance magicness.
Have a base class A, and a derived class B which overrides function template Func:
class A
{
A() {...};
~A() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
class B : public A
{
B() {...}
~B() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
(Note that Func is non-virtual, given the lack of support in C++ for templated virtual functions.)
Now have a mainprog API, class M:
class M
{
M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
{}
template <class T>
Evaluate(const String &sInput, T &tResult)
{
pInterface->Func<T>(sInput, tResult);
}
private:
const boost::shared_ptr<A> pInterface;
};
I want the function Evaluate here to support calls to functions on base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I re-designed class A and B to have templated functions.
Now the problem here is that if I pass a shared pointer of the base type to the derived type then Func of the base class will be called, not the derived class being pointed to.
How do I get around the lack of dynamic polymorphism here?
I've considered making class M a class template on the shared pointer type and having a static_cast in the constructor to ensure this type is of the base class type (A) or of a derived class.
What's the nicest way to do this? I'd prefer not to modify classes A and B to get around this problem but all suggestions are welcome.
Thanks.
Sounds like a double dispatch problem. Perhaps this would be a good place to implement the visitor pattern?
For example, create a class Evaluator, and for each T a subclass ConcreteEvaluator<T>. Give A and B methods that visit the Evaluator. Something like:
class Evaluator
{
virtual void visit_A(A* object);
virtual void visit_B(B* object);
};
template <typename T>
class ConcreteEvaluator : public Evaluator
{
public:
String* input_reference;
T& result_reference;
ConcreteEvaluator(String& input_reference_,T& result_reference_) :
input_reference(input_reference_),
result_reference(result_reference_) {}
virtual void visit_A(A* object) {
object->Func(input_reference,result_reference);
}
virtual void visit_B(B* object) {
object->Func(input_reference,result_reference);
}
}
class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}
class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}
For each subclass of A, a new method must be added to ConcreteEvaluator, so that this technique works best if A's class hierarchy is stable. And for each subclass of A, it must have an apply_evaluator function defined properly.
On the other hand, this may be total overkill. For about the same amount of work, you could always just pay the price to update M::Evaluate:
class M
{
...
void Evaluate(const String& sInput, T& tResult)
{
// try to downcast to each subclass of A. Be sure to check
// sub-subclasses first
try
{
dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
return;
}
catch (std::bad_cast& ) { }
...
// nothing worked. It must really be an A
pInterface->Func(sInput,tResult);
}
...
};
I've show in the question Templatized Virtual function how to use type erasure to get some of the effects of virtual member function. Depending on what you want to do in Func(), you can use the same technique here.