The problem lies here HashTable = new (nothrow) ListSet [size]; .Short explanation:
You are allocating an array of ListSet objects and handing the returned pointer to a Set * . This is not how inheritance works - you should allocate an array of Set pointers instead, and then allocate a ListSet object for each pointer. In code, that is:
int nSize = ...;
Base ** ppStuff = new Base * [nSize];
for( int i = 0; i < nSize; ++i )
ppStuff[i] = new Derived();
...
for( int i = 0; i < nSize; ++i )
delete ppStuff[i];
delete [] ppStuff;
Long explanation:
Every class that has virtual functions has a static virtual table - that's essentially an array of function pointers, one for each virtual function. Hidden from the programmer, the compiler adds a member variable - a pointer to that v-table. So your Set class actually looks something like this (in pseudocode):
class Set
{
public:
typedef string T;
virtual void Add(const T& key) = 0;
virtual bool Contains(const T& key) = 0;
virtual void Print() = 0;
virtual void Remove(const T& key) = 0;
function_ptr * __vfptr; // a pointer to a function pointer
static function_ptr __vftable[] = { &Set::Add, &Set::Contains, &Set::Print, &Set::Remove };
__vfptr = &Set::__vftable[0];
};
and the ListSet class:
class ListSet : public Set
{
...
static function_ptr __vftable[] = { &ListSet::Add, &ListSet::Contains, &ListSet::Print, &ListSet::Remove }; // this table is different from the Set one
__vfptr = &ListSet::__vftable[0];
};
When calling a virtual function through a base pointer, the v-table is checked to determine the correct version of the function to be executed.
Now, back to your problem - "HashTable[0] works fine but HashTable[1] gives the segmentation fault":
Assuming 32-bit architecture, the size in bytes of the Set class is 4 bytes (the hidden __vfptr pointer), whereas the ListSet class is 8 bytes (the __vfptr pointer, and the Node * first ). HashTable = new (nothrow) ListSet [size]; allocates size ListSet objects, that you try to access through a Set pointer; Looking at the memory, it is something like this (each cell is 4 bytes):
ListSet obj #1 ListSet obj #2 ListSet obj #size
+---------+---------+---------+---------+ +---------+---------+
| __vfptr | first | __vfptr | first | ... | __vfptr | first |
+---------+---------+---------+---------+ +---------+---------+
^ ^ ^ ^ ^ ^
HashTable[0] | HashTable[2] | HashTable[2*size-2] |
HashTable[1] HashTable[3] HashTable[2*size-1]
So what happens is that when you call HashTable[0].Print() , the v-table is checked, &ListSet::Print is resolved and executed, and all is fine. When you call HashTable[1].Print() however, a pointer to the v-table is expected in the place where first is; that pointer is invalid hence the segmentation fault.
The solution is to allocate an array of Set pointers first, and then the ListSet objects - that way the v-table will be in the correct place.