Communication Gap between .h and .cpp

I am implementing a dynamic array class. The following is my header file and then my implementation file:

---------------------------------------------------------------------------------
#ifndef DINO_ARRAY_H
#define DINO_ARRAY_H
#include <cstdlib>
using namespace std;

template <class Item>
class dinorray
{
static const size_t DEFAULT_CAPACITY = 10;
public:
//Constructors/Destructors
dinorray( size_t initial_capacity = DEFAULT_CAPACITY);
dinorray( const dinorray& source);
~dinorray();
//Constant Member Functions
size_t get_size() const;
size_t get_capacity() const;
Item print_current() const;
size_t distance_from_head() const;
Item random_access(size_t index) const;
//Modification Member Functions
void recapacitate();
void set_capacity(size_t new_capacity);
void insert( const Item& new_item);
void attach (const Item& new_item);
void remove_target(const Item& target);
void remove_current ();
void step_forward();
void step_backward();

//Operators
bool operator == (const dinorray& rhs);
void operator = (const dinorray& rhs);
void operator += (const dinorray& rhs);
dinorray operator + (const dinorray& rhs);

private:
Item* data;
size_t used;
size_t capacity;
size_t current_pos;
};
#endif

---------------------------------------------------------------------------------


#include "dinorray.h"
#include <algorithm>

using namespace std;

//Constructors and Deconstructors
template <class Item>
dinorray::dinorray(size_t initial_size = dinorray::DEFAULT_CAPACITY)
{
data = new Item[initial_capacity];
capacity = initial_capacity;
used = 0;
current_pos = 0;
}

template <class Item>
dinorray::dinorray( const dinorray& source)
{
//this implementation is identical to the = operator implementation
data = new Item[rhs.get_capacity()];
capacity = rhs.get_capacity();
used = rhs.get_size();
current_pos = rhs.distance_from_head();
copy(rhs.data, rhs.data + rhs.used, data)
}

dinorray::~dinorray()
{
delete [] data;
}

//Constant Member Functions
size_t dinorray::get_size() const
{
return used;
}


size_t dinorray::get_capacity() const
{
return capacity;
}

template <class Item>
Item dinorray::print_current() const
{
return data[current_pos];
}

size_t dinorray::distance_from_head() const
{
return current_pos;
}

template <class Item>
Item dinorray::random_access(size_t index) const
{
if (index < used)
return data[index];
}


//Modification Member Functions

template <class Item>
void dinorray::recapacitate()
{
dinorray temp(this);
data = new Item[(2 * get_capacity()) + 1 ];
capacity = (2 * get_capacity()) + 1;
//the endpoints of the following line may be faulty
copy(temp, temp + temp.get_capacity(), data);
}

void dinorray:: set_capacity(size_t new_capacity)
{
dinorray temp(this);
data = new Item[new_capacity];
capacity = new_capacity;
//
copy(temp, temp + temp.get_capacity(), data);
}

void dinorray::insert(const Item& new_item)
{
if (get_size() == get_capacity())
{
this->recapacitate();
}

for (size_t count = used; count >= current_pos; --count)
{
data[count] = data[count-1];
}
--current_pos;
data[current_pos] = new_Item;
++used;
}

void dinorray::attach(const Item& new_item)
{
if (used == capacity)
{
this->recapacitate();
}

for (size_t count = used; count > current_pos; --count)
{
data[count] = data[count-1];
}
data[current_pos] = new_item;
++used;
}

template <class Item>
void dinorray::remove_target(const Item& target)
{
Item* temp;
size_t remove_pos; // the place of the item to remove

temp = find(data, data+(used-1), target);
for (size_t count = 0; (count < used); ++count)
{
if (data[count] == *temp)
{
remove_pos = count;
break;
}
}

for (size_t count = remove_pos; count < used; ++count)
{
data[count] = data[count+1];
}

--used;
}

void dinorray::remove_current()
{
for (size_t count = current_pos; count < used ; ++count)
{
data[count] = data[count+1];
}

--used;
}

void dinorray::step_forward()
{
if (current_pos < used)
current_pos++;
}

void dinorray::step_backward()
{
if (current_pos != 0)
current_pos--;
}

//Operators

void dinorray::operator == (const dinoarray& rhs)
{
//to be equal, two dinorrays need not have the same current pos
bool is_equal = true;

if (this.used != rhs.get_size() or get_capacity() != rhs.get_capacity())
is_equal = false;
else
{
for (size_t count = 0; count < rhs.get_size(); ++count)
{
if (this.data[count] != rhs.data[count])
{
is_equal = false;
break;
}
}
}
return is_equal;
}

void dinorray::operator = (const dinorray& rhs)
{
data = new Item[rhs.get_capacity()];
capacity = rhs.get_capacity();
used = rhs.get_size();
current_pos = rhs.distance_from_head();
copy(rhs.data, rhs.data + rhs.get_size(), data);
}

dinorray dinorray::operator + (const dinorray& rhs)
{
dinorray new_dinorray;
new_dinorray.set_capacity(capacity() + rhs.capacity() );
//these two might be faulty
copy(this.data, this.(data + size() ), new_dinorray);
copy(rhs.data, rhs.(data+ rhs.size()), (new_dinorray + size() - 1));
new_dinorray.used = used + rhs.get_size();
new_dinorray.current_pos = 0;
}

void dinorray::operator += (const dinorray& rhs)
{
set_capacity(capacity + rhs.capacity);
copy(rhs.data, (rhs.data + rhs.get_size()), data + used);
used += rhs.get_size();
}

---------------------------------------------------------------------------------

Here is the command I use to compile:
g++ -c dinorray.cpp

When I attempt to compile my implementation file, I run into errors that indicate an incomplete communication between the implementation file and the header file. Whenever the function definitions try to access private member variables, the compiler says that the private member variable has not been defined. Whenever I type "dinorray::" in the implementation file, the compiler interprets the code as attempting to redefine the dinorray class.

How can I get these two files to talk to each other?





First can you post your code in code tags - the <> button on the right under format. The code is a nightmare to read otherwise. Do separate code tags for each file.

Next post your compiler output, it's easier to deal with than 200 lines of code. When you do that, the line numbers in the compiler output won't match those in the code tags because they start at 1, so can you let us know which lines match up.

Looking forward to helping if I can

You have to specify the template argument when defining the functions
1
2
3
4
template <class Item>
dinorray<Item>::dinorray(size_t initial_size)
{
	...
And template functions need to be in the same file that they are defined (I belive), no .cpp allowed.
I think that templates can be used in source files in c++11 (I remember reading something about that). But I don't know anything about that new syntax or how to do it.

But whenever you have a template function, it needs to be in the header.

One thing that I like to do is use an inline file to keep things neat. Example:
Header:
1
2
3
void myFunc(void);
template<class T> T myTemplateFunc(T);
#include "myTemplates.inl" 


myTemplates.inl:
template<class T> T myTemplateFunc(T) { return T; }

myFunc.cpp:
void myFunc(void) { return; }
Hmm, I did a quick test and it looks like you're right. Makes me wonder what was wrong with my code (weeks ago), that I wasn't compiling.
@ The Ideas Man: Sorry about my formatting and thanks for your interest.
@Peter 87: Thank you so much for your reminder. My code now compiles and is undergoing testing.
@LowestOne and Stewbond: your argument is going a little bit over my head. With some slight alterations, my current course is working out nicely.
I'm having one final problem that I could use help with.

I am creating an application program, named dinorray_test.cpp, for my dynamic array class which simply uses the copy constructor:

#include <"dinorray.h"
using namespace std;
int main()
{
dinorray<char> dinosaur;
return 0;
}

When I compile this with the command "g++ dinorray.o dinorray_test.o -o dinorray_test", I end up with linking problems. Constructing the dinorray<char> produces an error message: undefined reference to 'dinorray<char> :: dinorray()' . I have a similar error message for the destructor.

Did you define the dinorray constructors and member functions in the header?

EDIT: That < character on the include line should not be there
1
2
#include <"dinorray.h"
         ^
Last edited on
No, I did not. I declared the prototypes for the constructors and member functions in the header, but I defined them in my .cpp implementation file.
Try putting the functions in the .h

The very end of this page is where I got my info about "Templates and multiple-file projects":
http://www.cplusplus.com/doc/tutorial/templates/

For my little test I made a template function in main.h, so maybe this worked because my main() and the function definition were in main.cpp?
Last edited on
Topic archived. No new replies allowed.