C++ Implementing a pure virtual function over a template - c++

I am trying to implement an abstract class (ElementHolder) over a Template (TElementHolder). The function virtual T* Fun2() seems to work fine but the function virtual void Fun(T* element); creates the following compile error:
source>:60:23: error: cannot declare variable 'fireHolder' to be of abstract type 'FireElementHolder'
60 | FireElementHolder fireHolder;
| ^~~~~~~~~~
<source>:51:7: note: because the following virtual functions are pure within 'FireElementHolder':
51 | class FireElementHolder : public TElementHolder<Fire>
| ^~~~~~~~~~~~~~~~~
<source>:22:22: note: 'virtual void ElementHolder::Fun(Element*)'
22 | virtual void Fun(Element* element) = 0;
|
Can someone explain to me why the two functions create different results?
And if I can make this work somehow?
I am not sure if Implementing a pure virtual function over a template is the correct way of saying what I am doing here.
source: https://godbolt.org/z/qEYdrYfYa
#include <iostream>
//------------------------------------------------------------------------------------------
class Element
{
public:
virtual ~Element() {}
virtual void Fun() = 0;
};
class Fire : public Element
{
public:
~Fire() {}
void Fun() { std::cout << "Fire" << std::endl; }
};
//------------------------------------------------------------------------------------------
class ElementHolder
{
public:
virtual ~ElementHolder() {}
virtual void Fun(Element* element) = 0;
virtual Element* Fun2() = 0;
};
template<class T>
class TElementHolder : public ElementHolder
{
public:
virtual ~TElementHolder();
virtual void Fun(T* element);
virtual T* Fun2();
};
template<class T>
TElementHolder<T>::~TElementHolder() {}
template<class T>
void TElementHolder<T>::Fun(T* element)
{
element->Fun();
}
template<class T>
T* TElementHolder<T>::Fun2()
{
std::cout << "Hello Fun2" << std::endl;
return new T();
}
class FireElementHolder : public TElementHolder<Fire>
{
};
//------------------------------------------------------------------------------------------
int main()
{
FireElementHolder fireHolder;
auto instance = fireHolder.Fun2();
fireHolder.Fun(instance);
instance->Fun();
}

There is a well-known problem with your design.
You have two parallel class hierarchies, Elements and ElelementHolders. You want each concrete ElementHolder to accept a pointer or reference to a corresponding Element. So you add a pure virtual function to the base class
class ElementHolder {
virtual void Fun(Element* element) = 0;
and override it in each derived class (I de-templatized your hierarchy for ease of exposition, there is a T instead of Fire in your code, but it doesn't really affect anything):
class FireHolder : public ElementHolder {
virtual void Fun(Fire* fire) { ... }
Which is a very natural and sensible choice.
Except that it doesn't work at all, because void Fun(Fire* fire) doesn't override void Fun(Element* element). They are completely independent functions.
Now how do you solve this problem? There are two very different ways.
Get rid of ElementHolder::Fun altogether.
Change void Fun(Fire* fire) to void Fun(Element* fire). Cast fire to Fire* inside.
How does one cope without ElementHolder::Fun? Simply, just don't call it ;) You cannot safely use it anyway. The signature Fun(Element*) says that any element can be passed. In fact you can only pass Fire* to a FireHolder, and any other element is an error (so the signature lies---not a good idea). If you only have an ElementHolder and an Element *, there is no guarantee you can call Fun.
If you absolutely must call ElementHolder::Fun, then #2 is your only option.

Related

Can I call method in each base recursively without manually typing base::Method()?

The content
The question
Example
Why do I need it
Hi.
The question
I am facing a problem. I have a class A that has a base B (is polymorphic). In B class is method Print(), wich is virtual. In A class is also Print(). virtual.
Lets say I am given an A type object (or pointer), stored in B variable
B * object = new A();
And by calling
object->Print();
It calls the method in A class, but I also want it to call method in B class.
Technically
I want to call the method for each child until i reach class that has no child
This can be done as follows:
Example
class A
{
public:
virtual void Print() const override
{
cout << "A" << endl;
}
};
class B : public A
{
public:
virtual void Print() const override
{
cout << "B" << endl;
A::Print(); // i do not want to call it here...
}
};
The problem is that I do want not to be forced to call the
A::Print();
Why
Yes, you might be asking, what is the deal...
I have very long inheritance chain. (lets say that there are like 15 - 20 classes in the inheritance chain).
In a game, each one does some little thing.
Lets say
class GameObject
{
public:
virtual void Update() const
{
//updates position, recounts it towards screen
}
};
class Character : public GameObject
{
public:
virtual void Update() const override
{
// Updates lives, movement
}
};
class Warrior : public Character
{
public:
virtual void Update() const override
{
// Updates armor, specific stuff
}
};
Now this example is very simplified. Problem is, that if i forget to add a call base::Update() Then I am worndering why does it not work. Looking for such a misstake is hard. I mean, if there any way around it?
Thank you very much indeed for any responses.
Have a nice day
If indeed every class must call the base function, one way to ensure the functionality is enforced is to use the template pattern.
class GameObject
{
public:
void Updater()
{
Update(); // this is a virtual call
GameObject::Update(); // now call base
}
virtual void Update() const
{
}
};
class Character : public GameObject
{
public:
virtual void Update() const override
{
// Updates lives, movement
}
};
class Warrior : public Character
{
public:
virtual void Update() const override
{
// Updates armor, specific stuff
}
};
class Character : public GameObject
{
public:
virtual void Update() const override
{
// Updates lives, movement
}
};
class Warrior : public Character
{
public:
virtual void Update() const override
{
// Updates armor, specific stuff
}
};
Then always call YourObject::Updater(); instead of YourObject::Update(). The Updater function will call your object's Update function, and then return and call the base class Update.
There was once a proposal to get all the bases of a given type (N2965) which gcc actually implemented in <tr2/type_traits>. So, if portability is not a concern and you happen to be using gcc, you can write a catch-all like so:
struct A {
virtual ~A() = default;
virtual void print() { print_all(*this); }
void print_one() { std::cout << "A\n"; }
protected:
template <class T>
void print_all(T& object) {
object.print_one();
print_all(object, typename std::tr2::bases<T>::type{});
}
template <class T, class... Bases>
void print_all(T& object, std::tr2::__reflection_typelist<Bases...> ) {
using swallow = int[];
(void)swallow{0,
(static_cast<Bases&>(object).print_one(), 0)...
};
}
};
This splits up print(), which prints everything, and print_one() which just prints the one specific type. You just have your print() call print_all() with itself:
struct B : A {
void print() override { print_all(*this); }
void print_one() { std::cout << "B\n"; }
};
struct C : B {
void print() override { print_all(*this); }
void print_one() { std::cout << "C\n"; }
};
Otherwise, you'll have to wait for one of the reflection proposals to get adopted.

Class design complication (C++)

My classes are
Base
Derived_A
Derived_B
Parent
Child_One
Child_Two
Base has two signature functions:
virtual void foo( const Parent& ) = 0;
virtual void bar( const Base& ) = 0;
, which other parts of the program expect.
The problem is:
Derived_A treats Child_One and Child_Two the same. But Derived_B treats them differently.
How should I implement this?
One way is to find out what kind of object is passed to Derived_B.foo. This would be apparently "a design flaw".
The other way I tried is to change the signature functions as:
class Base
{
class Derived_A;
class Derived_B;
// virtual void bar( const Base& ) = 0;
virtual void bar( const Derived_A& ) = 0;
virtual void bar( const Derived_B& ) = 0;
}
class Derived_A: public virtual Base
{
virtual void foo( const Parent& ) = 0;
}
class Derived_B: public virtual Base
{
virtual void foo( const Child_A& ) = 0;
virtual void foo( const Child_B& ) = 0;
}
But now the bar function cannot use Base.foo. So I have to write the bar function twice, although the code is exactly the same.
Are there any other ways to deal with the problem? which one do you suggest?
P.S. I couldn't think of a good title. Please feel free to modify it.
The problem you are describing is called Double Dispatch. The link describes the problem and a few possible approaches to a solution (including polymorphic function signatures and the visitor pattern).
Without details of what the two type hierarchies' relation is with each other and how they interact, it's impossible to say what approach is appropriate. I've composed an overview of the other answers and another viable alternative that can be extended to the visitor pattern which was mentioned in a comment.
Performing the polymorphic behaviour in the children implementing a virtual function in Parent as already suggested by Joey Andres is quite typical object oriented solution for this problem in general. Whether it's appropriate, depends on the responsibilities of the objects.
The type detection as suggested by Olayinka and already mentioned in your question certainly smells kludgy, but depending on details, can be the minimum of N evils. It can be implemented with member function returning an enum (I guess that's what Olayinka's answer tries to represent) or with a series of dynamic_casts as shown in one of the answers in the question you linked.
A trivial solution could be to overload foo in Base:
struct Base {
virtual void foo(const Parent&) = 0;
virtual void foo(const Child_Two&) = 0;
};
struct Derived_A: Base {
void foo(const Parent& p) {
// treat same
}
void foo(const Child_Two& p) {
foo(static_cast<Parent&>(p));
}
};
struct Derived_A: Base {
void foo(const Parent& p) {
// treat Child_One (and other)
}
void foo(const Child_Two& p) {
// treat Child_Two
}
};
If there are other subtypes of Base that treat Child_One and Child_Two the same, then the implementation of foo(const Child_Two&) may be put in Base to avoid duplication.
The catch of this approach is that foo must be called with a reference of proper static type. The call will not resolve based on the dynamic type. That may be better or worse for your design. If you need polymorphic behaviour, you can use the visitor pattern which essentially adds virtual dispatch on top of the solution above:
struct Base {
foo(Parent& p) {
p.accept(*this);
}
virtual void visit(Child_A&) = 0;
virtual void visit(Child_B&) = 0;
};
struct Parent {
virtual void accept(Base&) = 0;
};
struct Child_A: Parent {
void accept(Base& v) {
v.visit(*this);
}
};
// Child_B similarly
struct Derived_A: Base {
void treat_same(Parent&) {
// ...
}
void visit(Child_A& a) {
treat_same(a);
}
void visit(Child_B& b) {
treat_same(b);
}
};
struct Derived_B: Base {
void visit(Child_A&) {
// ...
}
void visit(Child_B&) {
// ...
}
};
There's a bit more boilerplate, but since you seem very averse to implementing the behaviour in the children, this may be good approach for you.
You could've easily made a virtual foo method in Parent. Since you want Derive_A to treat all Parent's subclasses the same, why not implement a class that does just that in Parent. That is the most logical thing, since chances are, if you want to do the same to both of them, then both of them must have similar data, which is exist in Parent.
class Parent{
virtual void treatSame(){
// Some operations that treat both Child_A, and Child_B
// the same thing to both Child_A and Child_B.
}
virtual void foo() = 0;
}
Since you want Derived_B to do different operations in both Child_A and Child_B, take advantage of polymorphism. Consider the rest of the classes below:
class Child_A : public Parent{
virtual void foo(){
// Foo that is designed for special Child_A.
}
}
class Child_B : public Parent{
virtual void foo(){
// Foo that is designed for special Child_B.
}
}
class Base{
virtual void foo(Parent) = 0;
virtual void bar(Base) = 0;
}
class Derived_A: public Base
{
virtual void foo( Parent& p){
p.treatSame();
}
}
class Derived_B: public Base
{
virtual void foo( Parent& p){
p.foo(); // Calls appropriate function, thanks to polymorphism.
}
}
A possible usage is the following:
int main(){
Child_A a;
Child_B b;
Derived_A da;
da.foo(a); // Calls a.treatSame();
da.foo(b); // Calls a.treatSame();
Derived_B db;
db.foo(a); // Calls a.foo();
db.foo(b); // Calls b.foo();
}
Note that this will only work when the parameters are pointer or reference (I prefer to deal with reference when possible). Virtual dispatch (selecting appropriate function) won't work otherwise.
I'm not sure of the syntax but you get the gist.
class Base{
virtual void bar( Base ) = 0;
virtual void foo( Parent ) = 0;
}
class Derived_A: public virtual Base{
virtual void foo( Parent ) = 0;
}
class Derived_B: public virtual Base{
virtual void foo( Parent ){
//switch case also works
return parent.get_type() == Parent::TYPE_A ? foo_A((Child_A)parent) : foo_B((Child_B)parent);
}
virtual void foo_A( Child_A ) = 0;
virtual void foo_B( Child_B ) = 0;
}
class Parent{
virtual int get_type() = 0;
}
class Child_A: public virtual Parent{
return Parent::TYPE_A;
}
class Child_B: public virtual Parent{
return Parent::TYPE_B;
}

accessing non-template base class virtual function from template derived class

I'm trying to understand the template and inheritance. I have a base class as follows:
class Base
{
public:
virtual ~Base() {}
virtual void setId(u_int8_t id)
{
m_id = id;
}
private:
u_int8_t m_id;
};
and a derived template class as follows:
template <typename T>
class Data : public Base
{
public:
virtual void setId(u_int8_t id)
{
this->setId(id);
}
inline void setData(const T& data)
{
m_data = data;
}
inline T& data()
{
return m_data;
}
private:
T m_data;
};
this code compiles fine but crashes at run time. Why is this happening?
You get a stack overflow because setId keeps calling itself. To call the setId in the base class, use
virtual void setId(u_int8_t id)
{
Base::setId(id);
}
This function:
virtual void setId(u_int8_t id)
{
this->setId(id);
}
It is calling itself recursively, until the process runs out of stack space and you get a crash.
To call a function from the base-class you have to use the scope operator:
Base::setId(id);
The setId() function recursively calls itself forever. You want:
virtual void setId(u_int8_t id)
{
Base::setId(Id);
}
You don't actually need setId(u_int8_t id) in Data. The method is inherited from Base.
If you are intending to provide a different implementation in derived class, and use in this different implementation the implementation of the Base, then use Base::setId(id) (as Joachim Pileborg pointed out)
P.S.: Actually, there is nothing specific to templates in your question.

Using CRTP with virtual inheritance

I have a hierarchy of nodes, where "diamond" can occurred.
Every node must be clonable but I don't want to write clone method to every node. So I use CRTP.
class Node
{
public:
Node(){}
Node(Fill*) { }
virtual ~Node() {}
virtual Node * clone() const = 0;
virtual void id() { std::cout << "Node\n"; }
};
//====================================================================
template <typename Base, typename Derived>
class NodeWrap : public Base
{
public:
NodeWrap() { }
NodeWrap(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
works as follows:
class NodeA : public NodeWrap<Node, NodeA>
{
public:
typedef NodeWrap<Node, NodeA> BaseClass;
NodeA() { }
NodeA(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeA\n"; }
};
First question:
There is know BUG in VS when "covariance is used with virtual inheritance".
Is there a way to overcome the bug, and still have covariant types is clone method?
I changed return type to be Node instead of Base. I can live with that, but I would like to have Base as return type
Second question:
Problem occurred when multiple inheritance comes to play. I created new wrapper, which inherits virtually
template <typename Base, typename Derived>
class NodeWrapVirtual : public virtual Base
{
public:
NodeWrapVirtual() { }
NodeWrapVirtual(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
and now building diamond structure:
class NodeB : public NodeWrapVirtual<Node, NodeB>
{
public:
typedef NodeWrapVirtual<Node, NodeB> BaseClass;
NodeB() { }
NodeB(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeB\n"; }
};
//====================================================================
class NodeC : public NodeWrapVirtual<Node, NodeC>
{
public:
typedef NodeWrapVirtual<Node, NodeC> BaseClass;
using BaseClass::clone;
NodeC() { }
NodeC(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeC\n"; }
};
and problematic diamond node:
class NodeD : public NodeWrap<NodeB, NodeD>,
public NodeWrap<NodeC, NodeD>
{
public:
typedef NodeWrap<NodeB, NodeD> BaseClassB;
typedef NodeWrap<NodeC, NodeD> BaseClassC;
NodeD() { }
NodeD(Fill * f) : BaseClassB(f), BaseClassC(f) { }
using BaseClassB::clone; // (1)
virtual NodeD *clone() const { return new NodeD(*this); } // (2)
virtual void id() { std::cout << "NodeD\n"; }
};
where are 2 lines I am curious about. (line (1) and (2))
If both lines are removed, there is oblivious compile error, because there is ambiguous clone method (from every parent). Since I don't use covariant return types, there should work clone method form each parent, so i use line (1) but it doesn't work. Still ambiguous.
So I use line (2) and it works.
Is there a nice way, to avoid writing line (2)?
HERE is full working example on ideone.
First you should be very carefull to use virtual inheritance with members inside the virtual base (look at https://stackoverflow.com/a/1193516/1918154, "Effective C++", item 20: "Avoid data members in public interfaces" and http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8). Your node gets an pointer to a fill which is not used, but it looks like you need it somewhere.
Your problem can be solved when you move the inhertance relationship (public virtual and public) in the base class for your NodeWrap.
template <typename Base>
class InheritVirtual
: public virtual Base
{};
template <typename... Bases>
class InheritBases
: public Bases...
{
virtual Node* clone() const = 0;
virtual void id() const = 0;
};
class NodeB : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeC : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeD : public NodeWrap<InheritBases<NodeB,NodeC>, NodeD>
{
//...
};
Running Example.
The pure virtual methods in InheritBases are needed because the so called domination rule (Dominance in virtual inheritance).
The problem to be solved is a way to transfer paramters to the right constructor in case of multiple bases. Unlike Node (wich is a virtual base) it is ok to let NodeB and NodeC have member variables and non trivial constructors.
Each virtual function must have a unique final overrider in each derived class. This has nothing to do with name lookup (the requirement is for the functions, not for their names), thus using is irrelevant.
Use a multi-base-classed node class template:
template <class Derived, class Base1, class Base2>
class node2 : // etc
// or use a variadic template if you have more than two bases
As for covariant returns, they are strictly unnecessary, if convenient. You can always split each virtual function into a private virtual and a public non-virtual. This comes handy if you want to return covariant smart pointers, which is not supported by the regular covariant return machinery at all.

Use non-virtual dispatch in a template

I want to call a member function which is virtual (inheritance is used in most places to keep things simple), but I want to force calling it using non-virtual dispatch sometimes, in performance critical places, and in such places the exact type is known compile time. I do this for performance reasons, on a platform where virtual call performance is bad. For most functionality the overhead of virtual functions is fine, but for a few it is not. I would like to avoid duplicating all functions as both virtual and non-virtual.
Example:
class Interface
{
public:
virtual void Do(){}
};
class Implementation: public Interface
{
public:
virtual void Do(){}
};
void DoIt(Interface &func)
{
func.Do();
};
int main()
{
Implementation a;
DoIt(a);
// can DoIt be constructed as a template to avoid virtual dispatch?
return 0;
}
If you know the exact type you can do it as:
template <typename StaticType>
void DoIt(Interface &func)
{
static_cast<StaticType&>(func).StaticType::Do();
};
Where you need to manually downcast to the type you need (static_cast is fine if you do know the type). Then you need to qualify the method call, do disable dynamic dispatch.
struct DerivedType : Interface {
virtual void Do() { std::cout << "Derived::Do" << std::endl; }
};
struct MostDerived : DerivedType {
virtual void Do() { std::cout << "MostDerived::Do" << std::endl; }
};
void processDerived( Interface & iface ) {
DoIt<DerivedType>( iface );
}
int main() {
MostDerived obj;
DoIt<Derived>( obj ); // Will call Derived::Do
}
Note that using the qualified name will disable dynamic dispatch, and that means that it will not be dispatched to the runtime type of the object, but to the type that you tell it to call.
I think you are looking for Curiously Recurring Template Pattern (CRTP) which enables you static polymorphism :
template <typename Derived>
class Base {
public:
virtual ~Base() {}
void foo() { Derived::func_in_derived(); }
};
class Derived : public Base<Derived> {
public:
void func_in_derived() {}
};