0

I'm trying to learn how to work with external class files in C++ and have hit a wall. Everything runs just spiffy in xcode, but when trying to run it in the command line I've gotten the following error.

From g++:

Undefined symbols for architecture x86_64: "GradeBook::GradeBook(std::basic_string, std::allocator >)", referenced from: _main in cc9lOO3b.o "GradeBook::getCourseName() const", referenced from: _main in cc9lOO3b.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status

Here's the source code for the class:

// GradeBook.h header file


#include <iostream>
#include "GradeBook.h" // include definition of class GradeBook

// constructor initializes couseName with string supplied as argument
GradeBook::GradeBook ( std::string name )
: courseName ( name ) // member initializer to initialize courseName
{
    // empty body
} // end GradeBook constructor

// function that sets the course name
void GradeBook::setCourseName ( std::string name )
{
    courseName = name; // store the course name in the objec
} // end function setCourseName

// function that gets the course name
std::string GradeBook::getCourseName() const
{
    return courseName; // returns the object's courseName
} // end function getCourseName

// function that displays a welcome message to the GradeBook user
void GradeBook::displayMessage() const
{
    // this statement calls getCourseName to get the
    // name of the course this Gradebook represents
    std::cout << "Welcome to the grade book for\n" << getCourseName() << "!" << std::endl;
} // end function displayMessage

Thanks for taking a look!

2 Answers2

0

You forgot to

#include <string>

xcode could have it indirectly included from <iostream> but it's not mandated, so just include it yourself to play it safe.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Thanks! that eliminated a couple errors, but I'm still getting this one: Undefined symbols for architecture x86_64: "_main", referenced from: start in crt1.10.6.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status – Chris Rukan Jun 10 '13 at 03:33
  • @ChrisRukan http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix – Luchian Grigore Jun 10 '13 at 03:36
0

You can't just compile one source file, you need to compile them all. The simplest way is to pass all of the source files on the command line to g++:

g++ main.cpp GradeBook.cpp # Other flags (e.g. "-o OutputFile", "-Wall", etc.)

If you only compile main.cpp, you'll see errors about undefined symbols for any symbols which would be defined in GradeBook.cpp, such as the GradeBook::GradeBook() constructor. Conversely, if you only compile GradeBook.cpp, you'll see errors about undefined symbols for any symbols which are defined in main.cpp, namely the main() function.

This command line recompiles every source file every time you run it. For small projects like this, that is fine, since you won't notice the compile time, but as your project grows, you'll find it much more convenient to only recompile files which have changed or include headers which have changed. You'd typically use a dependency tracker such as GNU Make for this. After doing the dependency analysis, it will recompile source files one at a time like this:

g++ main.cpp -c -o main.o $(CXXFLAGS)  # Compile main.cpp
g++ GradeBook.cpp -c -o GradeBook.o $(CXXFLAGS)  # Compile GradeBook.cpp

g++ main.o GradeBook.o $(LDFLAGS)  # Link two object files into executable

You can also do this manually, of course, but it's much simpler just to pass all of the source files to g++ at once, and it can do the compiling and linking all together.

And as Luchian Grigore mentioned, you do need to #include <string> in your source files in order to use the std::string class. Ordinarily, failure to do so would result in compiler errors, but your C++ standard library implementation just happens to #include <string> from inside <iostream>. You should not rely on this behavior—if you port your code to other platforms, it may very well fail to compile, so it's better to avoid that in the first place. But even if compiles successfully without that include, that wouldn't ever lead to the linker errors you're getting.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • Thanks much @AdamRosenfield and @LuchianGrigore! Obviously I'm a total newbie to this, and your help is greatly appreciated. – Chris Rukan Jun 10 '13 at 03:51