List inheritance in C++ - c++

I'm doing a program that involve a lot of lists of multiple class. I'm pretty sure it has a name but I don't really know how to call it, what I would like to do is to make a common list which contain some functions (like element insertion, getter...) which all lists inherit and can use functions of the common list. So my question is how to do it with an example if possible.
I've made a header code example below.
class CommonList {
public:
// Add some functions
// T here is not a class I've made.
void insere(T element);
T getElement(int id);
protected:
std::map<int,T> m_map;
};
class A {
public: A();
}
class B {
public: B();
}
class ListA : public CommonList {
// Tell the program that element T are ONLY object of class A.
// Like if I would have made this.
/*
public:
void insere(A element);
A getElement(int id);
protected:
std::map<int,A> m_map;
*/
};
class ListB : public CommonList {
// Same for B.
}

I'm pretty sure it has a name but I don't really know how to call it
The word you are looking for is a template class.
And this is how it is being done:
template <typename T>
class CommonList {
public:
void insert(T element){
/* Implement your insert function here */
};
T getElement(int id){
/* Implement your getElement function here */
};
protected:
std::map<int,T> m_map;
};
And then you can simply create any type of that list, for example:
int main(){
CommonList<int> int_list;
my_list.insert(7);
CommonList<double> double_list;
my_list.insert(4.3);
}
You may of course also inherit from this class to and override the functions as you wish.
class A{};
class ListA : public CommonList<A>{
// ...
};
Or as a template
template <typename T>
class ListT : public CommonList<T>{
// ...
};

Related

c++ std::map class with generic key

I have a family of classes, and each subclass needs a map but the keys will have different types, although they both will perform the exact same operations with the map. Also the value on both cases will be string.
So far I have code similar to the example below, my goal is to reuse code, by
having a generic key.
Without using any additional libraries besides STL
class A{
public:
/*
* More code
*/
};
class subA1 : public A{
public:
void insertValue(long id, std::string& value){
if(_theMap.find(id) == _theMap.end())
{
_theMap[id] = value;
}
}
private:
std::map<long,std:string> _theMap;
};
class subA2 : public A{
public:
void insertValue(std::string& id, std::string& value){
if(_theMap.find(id) == _theMap.end())
{
_theMap[id] = value;
}
}
private:
std::map<std::string,std:string> _theMap;
};
Simply make superclass A a template, move both _theMap and insertValue() to it, and use the correct template version in subclasses.
template <typename KeyT>
class A{
public:
void insertValue(KeyT id, std::string& value){
if(_theMap.find(id) == _theMap.end())
{
_theMap[id] = value;
}
}
private:
std::map<KeyT, std:string> _theMap;
};
class subA1 : public A<long> {};
class subA2 : public A<std::string> {};
You can merge subA1 and subA2 into a single template class, eg:
class A{
public:
/*
* More code
*/
};
template <typename KeyType>
class subA : public A {
public:
void insertValue(const KeyType &id, const std::string& value) {
if(_theMap.find(id) == _theMap.end()) {
_theMap.insert(std::make_pair(id, value));
}
}
private:
std::map<KeyType, std:string> _theMap;
};
You can then create typedefs as needed:
typedef subA<long> subA1;
typedef subA<std::string> subA2;
Or, if you need actual derived classes:
class subA1 : public subA<long>
{
...
};
class subA2 : public subA<std::string>
{
...
};
How about writing another small base class, say C<T> which is a template typename T and just includes a map<T, string> and your insert function. Then each new subclass of A will also be a subclass of C as well. So your subA1 will be public A, public C<long> etc.

wrapper to template class inherited by another class

template <class CollectionItem>
class Collection
{
void A();
// Many other utility functions
}
class ICollection
{
virtual void B() = 0;
}
class Base : public Collection<BaseItem>, public IBase
{
virtual void B();
}
Is there any way of offering Collection functions via ICollection interface without wrapping all the functions in Base class? ICollection : public Collection<CollectionItem> is not an option.
Bounty Update:
OK, so the original idea was to have Interface to all Collection classes. Before we continue, every CollectionItem also has Interface, let's call it ICollectionItem and ICollection only knows about ICollectionItem.
So what I did was create another template class as Interface to Collection template class - ICollection (pure virtual) accepting ICollectionItem(s). Collection class inherits this interface.
Every Collection class (inheriting Collection<CollectionItem> class) would also inherit it's Interface Collection class. That Interface then virtual inherits ICollection<ICollectionItem>. I'll just post the code :)
Here is the code:
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
template <class CollectionItem, class ICollectionItem>
class Collection
: public ICollection,
public virtual ICollection<ICollectionItem> // Weak point
{
private:
List<CollectionItem*> fContainer;
public:
Collection(void) {}
virtual ~Collection() {}
virtual const ICollectionItem* At(const int idx); // Casting GetAt result
virtual const TCollectionItem& GetAt(const int idx) const
virtual ListIterator<TCollectionItem> >* GetIterator(void) const;
virtual ListIterator<ICollectionItem> >* Iterator(void) const; // Weak point
}
Example usage:
class IBaseItem
{
public:
virtual int Number() = 0;
{
class BaseItem
: public IBaseItem
{
public:
virtual int Number();
void SetNumber(int value);
}
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
}
class Base
: public Collection<BaseItem, IBaseItem>,
public IBase
{
public:
BaseItem* GetItemByName(String name);
virtual IBaseItem* ItemByName(String name);
}
Weak points:
First is at using virtual inheritance ... lots written about it, not much to talk about, or is it?
Unable to access Iterator using ICollection interface. See ListIterator function, only first one can be implemented, the second one would require some kind of new List of IBaseItem. I decided to live with that and just use for loop.
Even tho I somehow managed to get what I wanted (With wrapping and casting), I would still like to hear an second opinion. I don't like using virtual inheritance, specially in such delicate situations - using Collections for application Base creation.
I can not see any other solution than calling some Collection method in Base implementation of IBase virtual methods.
class Base : public Collection<BaseItem>, public IBase
{
virtual void B()
{
A();
}
}
You say, and I quote:
I want to call Collection functions using IBase pointer
I really don't see what is to be done here besides dynamic_cast. It does exactly what you want it to do.
void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<BaseItem>*>(base);
if (coll) {
coll->A();
}
}
Your Collection class must have a virtual destructor.
You can, of course, offer a templated version, if you'd need different baseitems in different, scenarios for some reasons. This has bad code smell and I think your architecture is bad at this point, but oh well.
template <typename T> void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<T>*>(base);
if (coll) {
coll->A();
}
}
void test(IBase * p) {
fun<BaseItem5>(p);
}
If you have some other specific scenario in mind, please edit your question to say what you mean.
Hmm...So you wanna to reuse the Collection class's utility functions, and you want to design a class which will implement an interface defined by IBase. As you mentioned above,"wrapping all the functions in Base class" is a way to offer Collection functions.
(1) Via inheritance,derived class has a good knowledge of Collection
class Derived:public Collection<DerivedType>,public IBase{};
or
template <typename T>
class Derived:public Collection<T>,public IBase{};
(2) Via inheritance,derived class knows little about Collection,but through IBase
class IBase : public Collection<BaseItem>{};
class Derived:public IBase{};
By (1),If you want to call Collection functions using IBase pointer,you have to wrap the functions.
By (2), any Derived instance is " a kind of " IBase which is "a kind of " Collection. So you can use IBase pointer to call Collection functions.
So,the key point is that the objects pointed by the IBase pointer should have the method you want to call.Wrap it or inherit it. I can not see any other solution than these two ways.
Edit: the idea is refined based on your example:
Here is an idea:
//generic interface can be kept as it is
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
class Empty
{
};
template <class CollectionItem , class BaseClass = Empty>
class GenericCollection
: public BaseClass
{
public:
const CollectionItem* At(const int idx);
// At and ItemByName are standard functions for a collection
CollectionItem* ItemByName(String name);
//note that here nothing has to be declared as virtual
};
//example usage:
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
};
class Base
: public GenericCollection<BaseItem, IBase >
{
public:
//nothing to be implemented here, all functions are implemented in GenericCollection and defined as virtual in IBase
//The definition of the functions has to be the same:
};
In collection you can implement whatever and in the interface you can define what ever you want to be virtual from your collection. The only thing is that you need to have some standard in naming convention for functions.
Hope this helps,
Raxvan.
From your comments in another answer, it seems you want a collection of interfaces, and an implementation of this interface. The simplest I can advise you is the following:
template<typename T>
class ICollection
{
public:
virtual iterator<T>* begin() const = 0;
};
template<typename T, typename TBase>
class Collection : public ICollection<TBase>
{
public:
iterator_impl<T>* begin() const { return whatever; }
};
Example:
class IItem {};
class Item : public IItem {};
class Base : public Collection<Item, IItem> {};
old answer:
Is there any way of offering Collection functions via IBase interface without wrapping all the functions in Base class ?
If I understood your problem, you want to use it like this:
void myfunc()
{
// ...
IBase* obj = ...;
obj->A();
obj->B();
}
I think here is a misunderstanding here: if you want A() to be callable from an IBase, then you have to add it to Ibase declaration.
If you want to use the Collection functions on an object, then you should cast this object to a Collection, via dynamic_cast for example.
Furthermore, if you have such a funcion:
void fun(IBase* base) { /* ... */ }
you cannot cast to a Collection*, since there are no relationship between these two classes, unless you have another way to be sure base is a Collection:
void fun(IBase* base)
{
if(base && base->isABaseItemCollection())
{
// Valid, since the real type was checked before
Collection* collection = (Collection*)base;
// ...
}
}
On a side note: you can generate bases almost automatically:
template
class Base : public Collection, public U {};
typedef Base BaseCollection;
According to comment/chat:
You have something like:
class IAnimal { /*...*/ };
class Cat : public IAnimal { /*...*/ };
class Dog : public IAnimal { /*...*/ };
class Cats
{
std::vector<Cat*> cats;
public:
Cat* at(size_t index) { return cats[index]; }
/*...*/
};
class Dogs
{
std::vector<Dog*> dogs;
public:
Dog* at(size_t index) { return dogs[index]; }
/*...*/
};
And you want to factorize some code using something like
class IAnimals
{
public:
std::vector<IAnimals*> animals; // or getter/setter which works with IAnimals.
/* some common factorized code */
};
// And so
class Cats : public IAnimals { /**/ };
class Dogs : public IAnimals { /**/ };
I propose, instead of creating class IAnimals, to use template functions as:
template <typename TAnimals>
void foo(TAnimals& animals)
{
Ianimals* animal = animals.at(42);
// ...
animal->eat(food);
// ...
}
You have to give compatible "interface" (names) to the type used in template.
Maybe you could have an operator() in IBase that would be delegated to Base?
class CollectionBase {};
template <class Item> class Collection: public CollectionBase {};
class IBase
{
public:
virtual CollectionBase* operator()() = 0;
};
class Base : public Collection<BaseItem>, public IBase
{
public:
virtual Collection<BaseItem>* operator()() { return this; }
};

Designing Inheritance with Abstract Return Types

Here's a rough image of what I'm trying to achieve (it won't compile, so consider it pseudocode). Please note that even though the example is based on public key cryptographic schemes, the question is about design patterns, templates and inheritance.
class CryptoProvider
{
public:
template <typename T>
virtual T Encrypt ()
{
T data;
return data;
}
};
class Paillier : public CryptoProvider
{
public:
typedef int Ciphertext;
Ciphertext Encrypt ()
{
Ciphertext data;
return data;
}
};
class ElGamal : public CryptoProvider
{
public:
struct Ciphertext
{
public:
int c1;
int c2;
};
Ciphertext Encrypt ()
{
Ciphertext data;
return data;
}
};
Basically, I want to provide some generic functionality in CryptoProvider, which can be overridden by the derived classes if required, because otherwise I would end up with lots of duplicate code. If Encrypt just needs to create a variable and call another function, then I don't want to write this code in every derived class, but, if a derived class needs to do some extra processing on the data, it should be able to overwrite the base method.
The biggest limitation that I've ran into is to somehow be able to override the Encrypt function by specifying completely different return types. Could somebody point me in the right direction on how to achieve this? Should I stick to traditional inheritance or should I try to go for compile-time / static polymorphism with CRTP? I have no idea where to start.
I also want to impose the derived classes to implement certain methods, but I'm not sure how to achieve this, if the solution to the first issue requires that I discard standard inheritance (and I won't benefit from virtual methods)...
All your child classes have the Ciphertext type defined to be different things. This suggest making it a template parameter of CryptoProvider.
template <typename T>
class CryptoProvider
{
public:
virtual T Encrypt () { ... }
typedef T Ciphertext;
};
class PaillierBase : public CryptoProvider<int> { ... }
IMHO CRTP is unnecessary here.
See another way to achieve this. Slightly round-about, though...
This provides the possibility of a common implementation based on templates and derivability. Only problem is that the CipherText definition cannot be inside the derived classes. I guess this wouldn't be a big problem for you. If you can define these classes in a global scope, you could get away with the additional derivation.
template <typename T>
class CryptoProvider
{
public:
virtual T Encrypt()
{
T data;
return data;
}
};
class PaillierBase
{
public:
typedef int Ciphertext;
};
class Paillier : public PaillierBase, public CryptoProvider<PaillierBase::Ciphertext>
{
public:
};
class ElGamalBase
{
public:
struct Ciphertext
{
public:
int c1;
int c2;
};
};
class ElGamal : public ElGamalBase, public CryptoProvider<ElGamalBase::Ciphertext>
{
public:
};
class CustomEncryptorBase
{
public:
struct Ciphertext
{
public:
char* c1;
int* c2;
};
};
class CustomEncryptor : public CustomEncryptorBase, public CryptoProvider<CustomEncryptorBase::Ciphertext>
{
public:
virtual CustomEncryptorBase::Ciphertext Encrypt()
{
CustomEncryptorBase::Ciphertext data;
// Do additional processing
return data;
}
};
int main()
{
ElGamal e;
ElGamalBase::Ciphertext c = e.Encrypt();
CustomEncryptor ce;
CustomEncryptorBase::Ciphertext c1 = ce.Encrypt();
return 0;
}
CRTP will work to provide compile-time overrideable functionality without need for virtual functions:
template <typename Derived> class CryptoProvider
{
public:
typename Derived::Ciphertext Encrypt() {
typename Derived::Ciphertext data;
return data;
}
};
class PaillierBase
{
public:
typedef int Ciphertext;
};
class Paillier : public CryptoProvider<PaillierBase>
{
public:
void test1() {
Encrypt();
}
};
class ElGamalBase
{
public:
struct Ciphertext {
int c1;
int c2;
};
};
class ElGamal : public CryptoProvider<ElGamalBase>
{
public:
void test2() {
Encrypt();
}
};
The return types need to be declared in a base class that must be a complete type by the time the CRTP template gets instantiated when you derive from it. The code below doesn't work, at least in pre-C11 compilers: at point P, the class ElGamal is not a complete type yet, thus CryptoProvider::Encrypt() can't be instantiated. I don't know if C11 changes anything here. It's a silly shortcoming of the language, IMHO.
// Doesn't work, unfortunately
class ElGamal : public CryptoProvider<ElGamal> /* P */
{
public:
struct Ciphertext {
int c1;
int c2;
};
void test2() {
Encrypt();
}
};
You can create a base class called CipherText in which you hold the cipher text. Then, you can subclass that to the specific type that you need to return. You can specify the return type as a base class pointer.
Of course, this answer might be right or wrong based on what you are trying to do.

C++ interface style programming. Need a way out

template <typename T>
class BaseQueue
{
public :
virtual void push_back(T value) = 0;
//other virtual methods
};
template <typename T>
class BaseDeque: public virtual BaseQueue<T>
{
public:
virtual void push_front(T value) = 0;
//other virtual methods
};
//Realisation
template <typename T>
class VectorQueue: public BaseQueue<T>
{
typedef typename std::vector<T> array;
private: array adata;
public:
VectorQueue()
{
adata = array();
}
void push_back(T value)
{
adata.push_back(value);
}
};
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//,
{
void push_front(T value)
{
VectorQueue::adata.push_front(value);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
VectorDeque<int> vd = VectorDeque<int>();//here is a error
int i;
std::cin >> i;
return 0;
}
I have such error: "C2259: 'VectorDeque' : cannot instantiate abstract class ...". How can I fix it? Class VectorQueue has realize every virtual method of BaseQueue class already. But the compiler doesn't know it. The only way I see is to write something like this:
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>//,
{
void push_front(T value)
{
VectorQueue::adata.push_front(value);
}
void push_back(T value)
{
VectorQueue::push_back(value);
}
//repeat it fo every virtual method of BaseQueue class (interface)
};
But it's awful.
push_back from BaseQueue isn't implemented on the BaseDeque side of the inheritance chain, and thus the childmost class is still abstract.
I think you're trying to force a class relationship here that shouldn't exist. Note how in the standard library deque and vector are distinct container types and things like queue adapt those containers to very precise interfaces rather than trying to inherit.
Even if you solve your diamond issue (or follow #Mark B's advice and keep them separate), you have a few other issues in there:
template <typename T>
class VectorQueue: public BaseQueue<T>
{
typedef typename std::vector<T> array;
private: array adata; // if this is private, VectorDeque can't reach it
public:
// constructors have an initializer section
// member variables should be initialized there, not in the body
VectorQueue()
// : adata() // however, no need to explicitly call default constructor
{
// adata = array();
}
};
template <typename T>
class VectorDeque: virtual public VectorQueue<T>, virtual protected BaseDeque<T>
{
void push_front(T value)
{
// if adata is protected, you can just access it. No need for scoping
/*VectorQueue::*/ adata.push_front(value);
// Error: std::vector doesn't have a method push_front.
// Perhaps you meant to use std::list?
}
};
Multiple inheritance and static polymorphism are of help, for instance:
// Abstract bases
template <typename T, typename Val>
class BaseQueue
{
public :
void push_back(Val val)
{
static_cast<T*>(this)->push_back(val);
}
// ...
};
template <typename T, typename Val>
class BaseDeque
{
public:
void push_front(Val val)
{
static_cast<T*>(this)->push_front(val);
}
// ...
};
// Concrete class
#include <deque>
template <typename Val>
class QueueDeque:
public BaseQueue<QueueDeque<Val>, Val>,
public BaseDeque<QueueDeque<Val>, Val>
{
std::deque<Val> vals;
public:
void push_front(Val val)
{
vals.push_front(val);
}
void push_back(Val val)
{
vals.push_back(val);
}
// etc..
};
int main()
{
QueueDeque<int> vd;// no more error
vd.push_front(5);
vd.push_back(0);
return 0;
}

Is there a way to access the private parts of a different instantiation of the same class template?

In my continuing adventure with templates, I've templated my Container class not just on the ItemType it holds, but also on a Functor argument that determines how it should order the items. So far, so good.
A little problem I've run into occurs when I want to copy the contents of one Container to another: If the two Containers have different Functor types, then they technically are unrelated classes. Therefore, Container A isn't allowed to access the non-public contents of Container B. Is there any good way to deal with this problem, other than making everything I need to access public? Some way to template a "friend" declaration, perhaps?
Example code to demonstrate the problem follows:
#include <stdio.h>
class FunctorA {};
class FunctorB {};
template <class ItemType, class Functor> class MyContainer
{
public:
MyContainer() : _metaData(0) {/* empty */}
template<class RHSFunctor> void CopyFrom(const MyContainer<ItemType, RHSFunctor> & copyFrom)
{
_metaData = copyFrom._metaData;
_item = copyFrom._item;
}
private:
int _metaData;
ItemType _item;
};
int main(int argc, char ** argv)
{
MyContainer<void *, FunctorA> containerA;
MyContainer<void *, FunctorB> containerB;
containerA.CopyFrom(containerB); // error, containerA::CopyFrom() can't access containerB's private data!
return 0;
}
You can make a base template class templated just on ItemType, keep the data there, have the full-fledged 2-args template subclass that base, AND put the copy-from in the base class as it doesn't depend on the functor anyway. I.e.:
template <class ItemType> class MyContainerBase
{
public:
MyContainerBase() : _metaData(0) {/* empty */}
void CopyFrom(const MyContainerBase<ItemType> & copyFrom)
{
_metaData = copyFrom._metaData;
_item = copyFrom._item;
}
protected:
int _metaData;
ItemType _item;
};
template <class ItemType, class Functor> class MyContainer:
public MyContainerBase<ItemType>
{
// whatever you need here -- I made the data above protected
// just on the assumption you may need to access it here;-)
};
As you point out, you can also use a friend function:
class FunctorA {};
class FunctorB {};
template <class ItemType, class Functor> class MyContainer
{
public:
MyContainer() : _metaData(0) {/* empty */}
template<class CmnItemType, class LHSFunctor, class RHSFunctor>
friend void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom
, MyContainer<CmnItemType, RHSFunctor> & copyTo);
private:
int _metaData;
ItemType _item;
};
template<class CmnItemType, class LHSFunctor, class RHSFunctor>
void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom
, MyContainer<CmnItemType, RHSFunctor> & copyTo)
{
copyTo._metaData = copyFrom._metaData;
copyTo._item = copyFrom._item;
}
int main(int argc, char ** argv)
{
MyContainer<void *, FunctorA> containerA;
MyContainer<void *, FunctorB> containerB;
Copy(containerB, containerA);
return 0;
}