C++ Templates and inheritance - c++

I have a class structure like this:
class MyImportantClass {};
class BaseA
{
public:
virtual void myFunction();
};
class CustomA : public BaseA
{
public:
virtual void myFunction();
};
class CustomB : public CustomA
{
public:
virtual void myFunction();
};
class CustomC : public CustomB
{
public:
virtual void myFunction();
};
So the classes derived from CustomB need to create object of classes derived from MyImportantClass. Additionally CustomC needs to create object of classes derived from CustomB.
At the moment I derive from the Custom-classes and override the virtual functions. But nearly all of the code is the same except the creating of the new object.
Now I decided to use templates. My Classes now look like this:
class BaseA
{
public:
virtual void myFunction();
};
class CustomA : public BaseA
{
public:
virtual void myFunction();
};
template <class T>
class CustomB : public CustomA
{
public:
virtual void myFunction();
};
template <class T, class ...temps>
class CustomC : public CustomB<T>
{
public:
virtual void myFunction();
};
But now I have the problem if I want to create a list of CustomB derived class objects I can not use QList<CustomB> (yeah, I use Qt so QList) I have to use QList<CustomB<SomeMyImportantClassDerivedClass>. So I need some way without passing a templateparameter to CustomB. If I would use QList<CustomA*> it would be logical incorret in my application. I want to keep it logical correct so other developers can read and understand my code easier.
I hope someone read this whole post and can help me.

You can create a QList<CustomA*> list. This way you can add pointers to all subclasses of CustomA including CustomC<whateverClass>.
To add:
list.append( new CustomC<whateverClass> );
But remember, since you call new you also have to delete your object, but since you're using QT, you could just give your new object a parent and have it deleted when it's parent is deleted.

Related

Virtual multiple interface

I need help for an implementation that uses multiple inheritance of Interfaces...
There is an existing code whith an interface which has a lot of functions. The instances are created using a factory.
class IBig
{
// Lot of pure virtual functions
};
And his inplementation:
class CBig: public IBig
{
// Implementation
}
I Want to split the interface in multiple smaller interfaces, but it should stay compatible to the existing code for some time.
Here is a sample of what I tried to do:
class IBaseA
{
public:
virtual void DoA() = 0;
};
class IBaseB
{
public:
virtual void DoB() = 0;
};
// The same interface, now based on multiple smaller interfaces
class IBig : public IBaseA, public IBaseB
{
};
class CBaseA: public IBaseA
{
public:
virtual void DoA()
{
printf("DoA\n");
}
};
class CBaseB: public IBaseB
{
public:
virtual void DoB()
{
printf("DoB\n");
}
};
// Inherit from base classes where the implementation is, and from IBig as
// the instance of CBig is returned as IBig.
class CBig: public CBaseA, public CBaseB, public IBig
{
};
The problem here is that the class CBig cannot be instanciated. The compiler says the functions DoA and DoB are pure virtual, even if they are inplemented in CBaseA and CBaseB. What should I do if i don't want to implement again the functions, just to call the function of the base class ?
NB: I know the design is ugly, but this is only temporary until the big interface can be replaced, and.... I want to understand ! ;-)
Thanks in advance !
Here we should use virtual inheritance. This feature assures that there is only one instance of your virtually-inherited base class when you instantiate a subclass. For your example, this would look like:
#include <cstdio>
class IBaseA
{
public:
virtual void DoA() = 0;
};
class IBaseB
{
public:
virtual void DoB() = 0;
};
// The same interface, now based on multiple smaller interfaces
class IBig : virtual public IBaseA, virtual public IBaseB
// ^ ^
{
};
class CBaseA: virtual public IBaseA
// ^
{
public:
virtual void DoA()
{
printf("DoA\n");
}
};
class CBaseB: virtual public IBaseB
// ^
{
public:
virtual void DoB()
{
printf("DoB\n");
}
};
// Inherit from base classes where the implementation is, and from IBig as
// the instance of CBig is returned as IBig.
class CBig: public CBaseA, public CBaseB, public IBig
{
};
int main()
{
CBig cb;
}
The above changes ensure that there are not extra declarations of DoA and DoB created when you inherit from IBaseA and IBaseB multiple times.

Extending a nested class method

I have encountered a virtual method in a nested class.
##classone.h
class ClassOne: {
public:
class InnerClass{
public:
virtual void method1();
...
##classone.cpp
void ClassOne::InnerClass::method1()
{
...
}
I am subclassing ClassOne and need to extend method1(). What need's to be done with the nested class in that situation?
What I tried
##subclassone.h
class SubClassOne: public ClassOne{
public:
virtual void method1();
##subclassone.cpp
void SubClassOne::InnerClass::method1()
{
##New implementation
}
But that gives a multiple definition of ClassOne::InnerClass::method1()
method1 belongs to ClassOne::InnerClass, not ClassOne. When you inherit from ClassOne, the nested class from base class becomes a member of the derived class, too, and you can reach it by qualifying with either ClassOne:: or SubClassOne::. Hence the double definition error regarding method1.
You'll need to sub-class InnerClass, too. If you still wish to derive from ClassOne, it would look like this:
class ClassOne {
public:
class InnerClass {
public:
virtual void method1();
};
};
void ClassOne::InnerClass::method1()
{
}
class SubClassOne : public ClassOne {
class DerivedInnerClass : InnerClass { //
virtual void method1();
};
};
void SubClassOne::DerivedInnerClass::method1()
{
}

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; }
};

template class inheritance syntax

My intention is to have some base class CBaseClass that, amongst other things, serves as a container to some members of type CBaseMember; then to derive a CDerivedClass : public CBaseClass that holds CDerivedMember : public CBaseMember.
I can't use a pointer to CBaseMember and initialize it with a CDerivedMember object in CDerivedClass because it's a multiple inheritance situation, CDerivedMember has an additional interface (a pure abstract base class) that is irrelevant to CBaseClass implementation but needs to be visible to CDerivedClass. Lots of dirty casting is something that I would very much like to avoid.
My solution to this problem was to make CBaseClass a template, like this:
//declaration
template <class Member>
CBaseClass
{
protected:
virtual void GenericMethod();
virtual void VirtualMethod() = 0;
Member* member;
};
//definition
template <class Member>
void CBaseClass<Member>::GenericMethod()
{
member->SomeMemberMethod();
}
and then to inherit CDerivedClass from it, like this:
//declaration
CDerivedClass : public CBaseClass<CDerivedMember>
{
protected:
virtual void VirtualMethod();
};
//definition
void CDerivedClass::VirtualMethod()
{
member->SomeDerivedMethod();
}
Predictably, this doesn't work (CBaseClass<CDerivedMember>::GenericMethod() is unresolved, for obivious reasons), but unfortunatly I don't know how to change my code to mean what I intend for it to mean.
Can anyone please explain how those things are done properly - or suggest another solution for my problem?
Thanks!
Well, you could keep the dirty typecasts at one place, encapsulated in your class. Therefore, it's not really dirty anymore.
class CBaseMember {
public:
virtual void SomeMemberMethod(){}
};
class CDerivedMember : public CBaseMember {
public:
virtual void SomeMemberMethod() { /* do other stuff */ }
virtual void SomeDerivedMethod() {}
};
//declaration
class CBaseClass
{
protected:
virtual void GenericMethod();
virtual void VirtualMethod() = 0;
CBaseMember* member;
virtual CBaseMember * getMember() {
return member;
}
};
//definition
void CBaseClass::GenericMethod()
{
getMember()->SomeMemberMethod();
}
//declaration
class CDerivedClass : public CBaseClass
{
protected:
virtual void VirtualMethod();
virtual CDerivedMember * getMember() {return static_cast<CDerivedMember *>(member);}
};
//definition
void CDerivedClass::VirtualMethod()
{
getMember()->SomeDerivedMethod();
}
In summary, you do the dirty typecasting inside the getMember() method of the derived class. At that point you should be sure that the type of the member is CDerivedMember anyway. So, as long as you know that the pointer you have is of type CDerivedClass you will have access to its CDerivedMember without typecasting. If you have to fall back to a CBaseClass pointer, you'll naturally fall back to the CBaseMember while accessing its member.
I suspect that you want to get rid of the templates, because the snippet you provided would work (if you added the class keyword to the declaration of your types).
If you want to avoid downcasts from CBaseMember* to CDerivedMember*, you can approach the situation with dynamic binding and covariance:
class CBaseClass {
private:
CBaseMember* const baseMember;
protected:
virtual CBaseMember* member() const {
// ^^^^^^^^^^^
return baseMember;
}
/* everything else you need here. Just never ever access `baseMember` directly */
};
class CDerivedClass : public CBaseClass {
private:
CDerivedMember* const derivedMember;
protected:
virtual CDerivedMember* member() const {
// ^^^^^^^^^^^^^^
return derivedMember;
}
/* everything else you need here. Just never ever access `derivedMember` directly */
};
However, this only works if you will never change the member to point somewhere else, because you cannot pull this trick with a setter: virtual void CBaseClass::member(CBaseMember*) cannot be overridden with virtual void CDerivedClass::member(CDerivedMember*).
Note that you will still be carrying the baseMember pointer in your CDerivedClass around, although it is never ever used. So if memory is important to you, this might not be viable.

Multiple inheritance hierarchy

I'm looking for a clean way of doing this since a long time. In my problem, there exist 3 classes not sharing any parent in common but each having some methods with the same name (A.doSomething, B.doSomething, C.doSomething). Hence, having the same function signature, class D inheriting from A and using method doSomething() will "look the same" to E inheriting from B or C .
Here is a sketch of what I'd like to be able to do:
class Base {
public:
void myMethod(void) { doSomething(); }
};
class Independent {
public:
doSomething();
};
clase Derived : public Base : public Independent {
(...)
};
int main(void) {
Derived *derivedObject = new Derived();
derivedObject->myMethod();
}
In this problem, object of type "Independent" is provided by a library that I cannot change. I would like to define a base class that uses methods that are going to be inherited later on. I couldn't find a proper way of doing this using virtual inheritance without causing ambiguous compiling.
You've got a nasty situation there. One solution to this would be using the Curiously Recurring Template Pattern to perform the inheritance at compile-time, like this:
template <typename D>
class Base {
public:
void myMethod(void) { static_cast<D*>(this)->doSomething(); }
};
class Independent {
public:
void doSomething();
};
clase Derived : public Base : public Independent {
/*...*/
};
int main(void) {
Derived *derivedObject = new Derived();
derivedObject->myMethod();
}
Alternatively, you could choose to put a middleman class in between to forward to Independent (I assume you have many classes deriving from the same Base and Independent, and just don't want to have to do this for each class).
template <typename D>
class Base {
private:
virtual void doSomethingImpl();
public:
void myMethod(void) { doSomethingImpl(); }
};
class Independent {
public:
void doSomething();
};
class IndependentWrapper : public Base : public Independent {
private:
void doSomethingImpl() { Independent::doSomething(); }
};
clase Derived : public IndependentWrapper {
/*...*/
};
int main(void) {
Derived *derivedObject = new Derived();
derivedObject->myMethod();
}