This is a problem that I have been staring at with befuddlement & confusion for 24 hours, and I've given up, something I rarely do.
I am making an *extremely simple* stack implementation, one that simply uses an array of fixed size (128 integers) to store my data. Do not worry about this primitive design -- it is this "undefined reference" error I am having trouble with, which pertains to a static data member.
I have three files: driver.cpp, Stack.h, and Stack.cpp. When I compile them (using g++) I get undefined reference errors for my 'numInstances' data member. If I remove the static member's declaration, definition and useage altogether the program compiles fine. Furthermore, when I combine all three files into one (with minor modifications of course, such as removing #IFNDEFs, multiple #include statements, etc.) file called test.cpp and compile it, it compiles perfectly! After reviewing my source code, as I believe you will agree, there must be some problem with my Stack.h file.
As to what this problem is, I do not know.
Stack.h
#include <iostream>
#ifndef MY_STACK
#define MY_STACK
const int STACK_CAPACITY = 128;
typedef int StackElement;
class myStack
{
public:
static int numInstances;
// Constructor
myStack();
~myStack();
bool empty() const;
void push(const StackElement& value);
void display(ostream& out) const;
StackElement top() const;
void pop();
private:
// Data members
StackElement myArray[STACK_CAPACITY];
int myTop;
};
#endif
Stack.cpp
#include <iostream>
using namespace std;
#include "Stack.h"
// Definition of Stack constructor.
myStack::myStack()
{
myTop = -1;
//numInstances++;
}
// Default destructor
myStack::~myStack()
{
//numInstances--;
}
// Definition of empty()
bool myStack::empty() const
{
return (myTop == -1);
}
// Definition of push()
void myStack::push(const StackElement& value)
{
if(myTop < STACK_CAPACITY - 1) // Preserve stack invariant
{
++myTop;
myArray[myTop] = value;
}
else
{
cerr << "*** Stack full -- can't add new value ***\n"
"Must increase value of STACK_CAPACITY in Stack.h\n";
exit(1);
}
}
// Definition of display()
void myStack::display(ostream& out) const
{
for(int i = myTop; i >= 0; i--)
out << myArray << endl;
}
// Definition of top()
StackElement myStack::top() const
{
if(!empty())
return (myArray[myTop]);
else
{
cerr << "*** Stack is empty -- returning garbage value ***\n";
return (myArray[STACK_CAPACITY - 1]);
}
}
// Definition of pop()
void myStack::pop()
{
if(!empty())
myTop--;
else
cerr << "*** Stack is empty -- can't remove a value ***\n";
}
driver.cpp
#include <iostream>
using namespace std;
#include "Stack.h"
int main()
{
unsigned number, remainder;
myStack stackOfRemainders;
char response;
stackOfRemainders.numInstances = 0;
do
{
cout << "Enter positive integer to convert : ";
cin >> number;
while(number != 0)
{
remainder = number % 2;
stackOfRemainders.push(remainder);
number /= 2;
}
cout << "Base-2 Representation : ";
while(!stackOfRemainders.empty())
{
remainder = stackOfRemainders.top();
stackOfRemainders.pop();
cout << remainder;
}
cout << endl;
cout << "\nMore (Y or N)? ";
cin >> response;
} while(response == 'Y' || response == 'y');
}
Like I said, if you put them all into one file they will compile fine, so why is numInstances an undefined reference when implemented into three separate files?
Well I believe in God, and the only thing that scares me is Keyser Soze.