Linking error

K

Kevin Grigorenko

Okay, everything seems simple enough but I get the following Link error:

TeXt.obj : error LNK2001: unresolved external symbol "private: static char *
TextDB::TextDB::myVersion" (?myVersion@TextDB@1@0PADA)

My environment is Visual Studio .NET, I think it's C++ 7 from the microsoft
visual studio versioning point of view.

Here is TeXt.h:

// Annoying MSVC++ warning:
#pragma warning( disable : 4290 )

// TeXt - Standalone Pure Text Database Management System

#ifndef TEXT_DB
#define TEXT_DB

#define TEXT_MAJOR_REVISION 1
#define TEXT_MINOR_REVISION 0
#define TEXT_BUILD 0

/*
Revision History:
-----------------
---------
- Created. I've run into too many situations
where something like this would have been
useful.
*/

//#include <bool.h>
#include <string>
#include <stdexcept>
/*

// If no bool.h, uncomment:
typedef short int bool;
#ifndef false
#define false 0
#endif
#ifndef true
#define true 1
#endif
*/

namespace TextDB
{
class TextDB
{
public:
// Constructors/Destructor:
TextDB(const std::string filename) throw(std::invalid_argument);
~TextDB();
TextDB(const TextDB &copy) throw(std::invalid_argument);

static const char *getVersion();
private:
// Private because it is illogical to instantiate a
// TextDB object without a filename
TextDB();

void initialize(std::string in_filename)
throw(std::invalid_argument);

std::string filename;
static char myVersion[20];
}; // class TextDB
} // namespace TextDB

#endif // #ifndef TEXT_DB

AND then here is TeXt.cpp:

//#include <bool>
#include <string>
#include <fstream>
#include "TeXt.h"
namespace TextDB
{
TextDB::TextDB(const std::string filename)
{
initialize(filename);
}

TextDB::~TextDB()
{
}

TextDB::TextDB(const TextDB &copy)
{
initialize(copy.filename);
}

const char *TextDB::getVersion()
{
return myVersion;
}

void TextDB::initialize(std::string in_filename)
{
sprintf(myVersion, "%d.%d.%d", TEXT_MAJOR_REVISION,
TEXT_MINOR_REVISION, TEXT_BUILD);
std::ifstream infile(filename.c_str(), std::ios_base::in);
if(!infile.is_open())
{
throw std::invalid_argument("Could not open database file <" +
filename + ">");
}
this->filename = in_filename;
infile.close();
} // initialize()
} // namespace TextDB

I'm sure the answer is simple, but I can't see it obviously.

Thank you very much!

Kevin Grigorenko
 
R

Ron Natalie

Kevin Grigorenko said:
static char myVersion[20];

This is only a declaration.

You must also define it. Put

char TextDB::myVersion[20];

inside the namespace TextDB in your cpp file.
 
M

Mike Wahler

Kevin Grigorenko said:
Okay, everything seems simple enough but I get the following Link error:

TeXt.obj : error LNK2001: unresolved external symbol "private: static char *
TextDB::TextDB::myVersion" (?myVersion@TextDB@1@0PADA)

My environment is Visual Studio .NET, I think it's C++ 7 from the microsoft
visual studio versioning point of view.

Here is TeXt.h:

namespace TextDB
{
class TextDB
{
public:
// Constructors/Destructor:
TextDB(const std::string filename) throw(std::invalid_argument);
~TextDB();
TextDB(const TextDB &copy) throw(std::invalid_argument);

static const char *getVersion();
private:
// Private because it is illogical to instantiate a
// TextDB object without a filename
TextDB();

void initialize(std::string in_filename)
throw(std::invalid_argument);

std::string filename;
static char myVersion[20];

This is only a declaration, it's not a defintion.
No storage is reserved. Do this in your implementation
file (inside your namespace 'TextDB':

char TextDB::myVersion[20];

I'd recommend replacing that char array with a std::string.

-Mike
 
K

Kevin Grigorenko

Ron Natalie said:
static char myVersion[20];

This is only a declaration.

You must also define it. Put

char TextDB::myVersion[20];

inside the namespace TextDB in your cpp file.

Thanks, that did it. So any variables declared static must explicitly be
defined? Can this be done inline?

Kevin Grigorenko
 
R

Ron Natalie

Kevin Grigorenko said:
Thanks, that did it. So any variables declared static must explicitly be
defined?
Yes

Can this be done inline?

No, with the exception of static integral constants. The implementations need
the definition to figure out which module actually allocates the storage for the
variable. This all harps back to an age old issue as to whether C (or C++)
could define the same data in multiple object files and have the linker fold
them all into the same object. The early C linkers did support this, but the
powers that were decided to not require this (although any linker that could
do seperate compilation of Fortran (common blocks) had to have the capability).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top