Method inheritance from abstract class - c++

I'm very new to C++ and I'm not quite sure how to override methods from base class.
I apologize for not translating the code to English prior to posting, but I don't think it would make any difference.
A summary of what I'd like to do is create an abstract base class for linked lists, then derive singly/doubly/multiply linked/circular lists from it etc.
Here is the code:
#ifndef __LISTA_H__
#define __LISTA_H__
class Elem;
class JulElem;
class Lista // Abstract list class
{
public:
Lista();
~Lista();
virtual void dohvatiGlavu() = 0;
virtual void dodajNaKraj(int vred) = 0;
virtual void dodajIza(Elem* elem, int vr) = 0;
virtual void obrisiIza(Elem* elem) = 0;
virtual bool prazna() = 0;
virtual int velicina() = 0;
protected:
class Elem
{
protected:
int vred;
};
virtual Elem* noviElem();
private:
Elem* glava;
};
class Jul : Lista // Singly linked list
{
public:
void dohvatiGlavu();
void dodajNaKraj(int vred);
void dodajIza(Elem* elem, int vr);
void obrisiIza(Elem* elem);
bool prazna();
int velicina();
private:
class JulElem : Elem
{
};
JulElem* noviElem();
};
This is the error I get:
error C2555: 'Jul::noviElem': overriding virtual function return type differs and is not covariant from 'Lista::noviElem'
I've mostly seen people use structs for list elements but I'm not sure how that would fit my case scenario because different types of lists require different types of structs.
Thanks

The problem is that the inheritance is private, so JulElem* is not covariant with Elem*. Use public inheritance:
class JulElem : public Elem
^^^^^^

The return type of the function can not be overrided. you should do like this:
in the base, define the function as:
virtual void noviElem(Elem** result);
The parameter "result" served as an output paramter

It seems like you need to use templates.
Here is an example :
template<class T>
T Add(T n1, T n2)
{
T result;
result = n1 + n2;
return result;
}

Related

C++ Implementing a pure virtual function over a template

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.

Virtual function in class template, that doesn't have the template type as parameter/return value

As far as I know, templated virtual functions aren't allowed/possible due to the undefined size of the vtable.
On the other hand, virtual functions inside a class template which don't use the template type seem to be allowed, right?
What about a virtual function that doesn't use the template type as parameter or return type but works on data of the template type? Would that be valid C++?
I have already done some testing and it seems to work.
My Code looks like this:
(Note: For reasons of readability this is only the basic structure, not the real code).
template<typename T>
class Base {
public:
virtual bool compare(void) {
// Basic implementation
return ((value1 + value2) < value3);
}
protected:
T value1, value2, value3;
}
/**
* Derived from Base<ComplexClass> where
* ComplexClass is a Class providing
* a int Value through .getInt()
**/
class Derived : Base<ComplexClass> {
bool compare(void) {
return ((value1.getInt() + value2.getInt()) < value3.getInt());
}
}
main {
Base<int> *intBase = new Base<int>();
Base<double> *doubleBase = new Base<double>();
Base<ComplexClass> *complexBase = new Derived();
intBase->compare(); // Should call base function
doubleBase->compare(); // Should also call base function
complexBase->compare(); // Should call the compare function of Derived
}
As far as i can tell this works like I excepted. Is this just a lucky coincidence or is this valid/good C++ style?
If it's valid, could someone please explain what's happening inside and why some people say it's forbidden/bad practice to derive from class templates and use virtual functions inside of class templates?
Thank you in advance!
PS: I know something similar could have been done by template specialization but I'd like to know if it's also possible this way.
Q As far as I know, templated virtual functions aren't allowed/possible due to the undefined size of the vtable.
A You can have virtual function in class templates.
Example code that compiles and links:
template <typename T>
struct Base
{
virtual T doSomething(T const& in) = 0;
Base(T const& data) : data_(data) {}
T data_;
};
struct Concrete : public Base<int>
{
Concrete(int d) : Base(d) {}
virtual int doSomething(int const& in)
{
return data_*in;
}
};
int main()
{
Concrete a(20);
int b = a.doSomething(10);
}
Q On the other hand, virtual functions inside a class template which don't use the template type seem to be allowed, right?
A The virtual functions of a class template can use anything -- not restricted to not using the template tye.
My example should make that clear.
Q What about a virtual function that doesn't use the template type as parameter or return type but works on data of the template type? Would that be valid C++?
A Yes, it will.
Again, my example should make that clear.
EDIT: Extended example
template <typename T>
struct Base
{
virtual T fun1(T const& in) = 0;
virtual T fun2(int in) = 0;
virtual int fun3(T const& in) = 0;
virtual int fun4(int in) = 0;
Base(T const& data) : data_(data) {}
T data_;
};
struct Concrete : public Base<int>
{
Concrete(int d) : Base(d) {}
virtual int fun1(int const& in)
{
return data_*in;
}
virtual int fun2(int in)
{
return fun1(in);
}
virtual int fun3(int const& in)
{
return fun1(in);
}
virtual int fun4(int in)
{
return fun1(in);
}
};
int main()
{
Concrete a(20);
int b = a.fun1(10);
int c = a.fun2(10);
int d = a.fun3(10);
int e = a.fun4(10);
}
This is perfectly valid. However, here you can have the same behaviour with specialization or just overloading, e.g.
template<typename T>
struct Base
{
bool compare() const { return val(value1) + val(value2) < val(value3); }
protected:
T value1, value2, value3;
private:
template<typename U>
static U val(U a) { return a; }
static int val(const ComplexClass& a) { return a.getInt(); }
};
Better keep virtual functions for when it's really needed.
And try to gather as much as possible shared code in a single place, minimizing what is to be specialized.

Abstract class methods implementation with subclasses of an other base class

I am trying to define an interface called "Algorithm" which has a pure virtual method insertData(InputData* input).
The implementation of the interface is called "Algorithm1" and i want to implement method "insertData" using as a parameter "SpecificData" which is a child of "InputData" class.
Is it possible without type casting?
Obviously with this code i get an error from the compiler that the virtual function "insertData" is pure within "Algorithm1".
class Algorithm{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class Algorithm1 : public Algorithm{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(SpecificData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class InputData{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
private:
int id;
};
class SpecifiData : public InputData{
public:
list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main(){
SpecificData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}
For insertData to be the same function (rather than "hiding" the original insertData, you need the two functions to have the same arguments (and same return type).
The whole idea of interfaces using virtual functions is that "they appear the same from the outside". You should be able to build a list of objects, and perform the same operation with the same input data for all of the objects in the list.
If you are breaking that principle, you are "doing it wrong".
No, it wouldn't make sense.
Think about the following scenario - you have a container (vector/set w/e) of Algorithm* type objects and a function that takes this container and a InputData* in as an input and then iterate over them and call insertData(in) on each of the objects in the container, this of course should work properly, but if one of the objects in your container is of type Algorithm1 what will happen then?
I think, this is a typical example of "Factory Method" in design pattern term.
class Algorithm
{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class InputData
{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
virtual list<int> getAdditionalNumbers() = 0;
private:
int id;
};
class Algorithm1 : public Algorithm
{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(InputData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class SpecifiData : public InputData
{
public:
// implementation
virtual list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main()
{
InputData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}

c++ abstract class takes derived class parameter

I want to make a class with a member function that takes a reference to another class, where both classes are derived from abstract classes. I get a compiler error that the class Container is abstract because it doesn't implement addElem().
class Ielem
{
public:
virtual void action() = 0;
};
class Elem: public Ielem
{
public:
void action() {};
void extra() {};
};
class Icontainer
{
public:
virtual void addElem(Ielem &elem) = 0;
};
class Container: public Icontainer
{
public:
void addElem(Elem &elem) { elem.extra(); };
};
int main(int argc, char* argv[])
{
Elem e;
Container c;
c.addElem(e);
return 0;
}
It seems like this ought to work, because any reference to an Elem is also a reference to an Ielem. It compiles if I make Container::addElem take a reference to an Ielem. But then Container::addElem() can't call Elem::extra() unless I use dynamic_cast, which isn't available on the embedded compiler I'm using, or a regular cast, which isn't type safe.
Suggestions?
It's the wrong way round: the base class Icontainer specifies that addElem can take any Ielem object as an argument, but in your derived class you accept only Elem. This is a "narrower" type, so the contract "I'll accept any Ielem you throw at me" specified in the base class is violated.
I think templates would be the solution here. You don't even need the base classes anymore. Something like this:
class Elem
{
public:
void action() {};
void extra() {};
};
template<typename ElemType>
class Container
{
public:
void addElem(ElemType &elem) { elem.extra(); };
};
int main(int argc, char* argv[])
{
Elem e;
Container<Elem> c;
c.addElem(e);
return 0;
}
As a bonus, you can now use Container with any type that has an extra() function, and it will just work.
The problem is simply that your virtual method doesn't have the same signature as the concrete method which is intended to overload it; so the compiler sees it as a different function entirely and complains because you haven't implemented void addElem(Ielem &elem). This is one solution, which you probably don't want--
class Icontainer
{
public:
virtual void addElem(Elem &elem) = 0; //Ielem -> Elem
};
It depends on all your other constraints but I think what I would do--and what seems to conform to general design guidelines, e.g. Sutter & Alexandreascu, would be to create an intermediate abstract class with the full interface--
class Melem: public Ielem
{
public:
// void action() {}; //Already have this form Ielem
void extra() = 0;
};
and then
class Icontainer
{
public:
virtual void addElem(Melem &elem) = 0;
};
class Container: public Icontainer
{
public:
void addElem(Melem &elem) { elem.extra(); };
//*Now* we're implementing Icontainer::addElem
};

C++: How to define a virtual function with generic return type?

I'm trying to define a base a class in C++ that has pure virtual methods to be implemented by children classes.
I would like to define setter and getter functions for basic types in the base class, but I would like the derived class to be able to determine the basic type of the getter and setter. For instance my base class would look like this:
class Value
{
public:
Value();
template <class T>;
virtual T getValue() = 0;
virtual void setValue(T val) = 0;
}
and my child class would look something like this:
class IntValue : public Value
{
public:
IntValue();
template <class T>
T getValue() {return _val};
void setValue(T val) {_val = val};
private:
int _val;
}
Of course the above code does not work. Any ideas on how to achieve this? Thanks in advance.
If I understood your problem correctly, rewriting your code to
template <class T>
class Value
{
public:
Value();
virtual T getValue() = 0;
virtual void setValue(T val) = 0;
};
class IntValue : public Value<int>
{
public:
IntValue();
int getValue() {return _val;}
void setValue(int val) {_val = val;}
private:
int _val;
};
should work
What you're asking for is not possible. In order to generate the right entries in the vtbl (or whatever similar structure the compiler might be using), the compiler needs to know what entries are going to be needed in the base class specifically. You can't just return a different type in a derived class and expect the base class to "know" about it in that way; as that would require a modification of the definition of the function template in the base class.
An example of how you might do that kind of modification of the base class using a class template (rather than a function template) can be seen in J_D's answer, but that still doesn't match your problem description exactly, because you wouldn't be able to create a Value and treat it polymorphicly.
C++ templates are essentially "fancy-pants find and replace" with the type -- when the compiler instantiates the function template, it generates a plain function with the typenames replaced. Note that this is very different than C# or Java "generics", which are completely different and rely on runtime support and a layer of indirection to achieve a similar effect. (Note though that this "find and replace" respects precedence rules and such, unlike C preprocessor macros :) )
If you really think about it too, this pattern does not make sense. What would this really look like on the client side of things?
class Value
{
public:
Value();
//Imagine if this were possible...
template <class T>;
virtual T getValue() = 0;
virtual void setValue(T val) = 0;
}
class IntValue : public Value
{
public:
IntValue();
int getValue() {return _val};
void setValue(int val) {_val = val};
private:
int _val;
}
class FloatValue : public Value
{
public:
FloatValue();
float getValue() {return _val};
void setValue(float val) {_val = val};
private:
float _val;
}
Now, you go to use this class:
void example(Value * ptr)
{
//What could you possibly say the type of "bar" is? There's no type that works!
???? bar = ptr->getValue();
delete ptr;
}
int main()
{
example(new IntValue());
example(new FloatValue());
}
As such, even if this were allowed, it wouldn't make much sense. You'd always have to downcast all the time, which would mean that the virtual keyword would be meaningless anyway.
Expanding on what #Billy ONeal said about a class template, this may work for your purposes:
template<typename Type>
class Value
{
public:
virtual Type getValue() = 0;
};
class IntValue : public Value<int>
{
public:
IntValue(int value)
: m_value(value)
{
}
int getValue()
{
return m_value;
}
private:
int m_value;
};