Reputation: 1
I have the following situation:
I have a List class that is using a ListNode class that is inherited in classes that wants to be put in a list.
struct _List_node_base
{
...
void _M_hook(_List_node_base* const __position);
void unhook();
};
template<typename _Tp>
class ListNode : public _List_node_base
{
...
typedef _Tp* pointer;
public:
pointer GetNext();
pointer GetPrev();
};
template<typename _Tp>
class List
{
...
};
I also have a HashTable class which similar to lists have a HashNode class. The HashNode use ListNode in order to be put in a list in the appropriate hash slot.
template<typename _KeyType, typename _ObjectType>
class HashNode : public ListNode<ObjectType>
{
...
public:
_KeyType GetHashKey()
};
template<typename _KeyType, typename _ObjectType, typename _HashFunctionType>
class HashTable
{
//example
template<typename _KeyType, typename _ObjectType, typename _HashFunctionType>
void HashTable<_KeyType, _ObjectType, _HashFunctionType>::Insert(_ObjectType *object)
{
uint pos = hashFunction(object->GetHashKey(), tableSize);
hashTable[pos].PushBack(object);
}
};
I have a class that wants to be both listable and hashable.
class A : public HashNode<SomeKeyType_t, A>, public ListNode<A>
{
...
};
The problem is that the compiles complains about that the members in List_node_base has an ambiguous base of class A.
Both in the Hash class and the List class, they use methods in ListNode and List_node_base directly on class A.
Basically, I want to make class A both hashable and listable but the ListNode functionality of HashNode should not be exposed outside the implementation of class HashTable.
Also the point of the classes are that they must be instrusive, dynamic allocations and copying classes is not allowed. Otherwise this would have been solved by creating a container class.
Upvotes: 0
Views: 739
Reputation: 1276
Could you possibly use STL / boost containers holding smart pointers (e.g. boost::shared_ptr) to get round the problem that your classes must be none-copy constructable and non-copy assignable?
Upvotes: 0
Reputation: 185852
I think a better design would be to avoid inheritance and use something like this instead:
template <typename _KeyType, typename _ObjectType>
struct HashEntry {
typedef ListNode<HashEntry> Node;
_KeyType key;
_ObjectType object;
...
};
BTW, _<uppercase-letter>...
is reserved for the implementation. You should shouldn't use it in your own symbol names.
Upvotes: 1
Reputation: 44181
I'm not sure I like the design, but in any case, you can resolve your issue by using virtual inheritance on _List_node_base.
Upvotes: 3
Reputation: 15872
Since HashNode is a derived class of ListNode, you have the same "parent" class twice in the object heirarchy.
Avoid Multiple inheritance of non-abstract classes as much as possible. If you absolutely need a class to be inherited from 2 base classes, you should reevaluate your design pattern and/or look into making interface (abstract) classes that your class can implement.
Upvotes: 0