Nicholas Hayden
Nicholas Hayden

Reputation: 523

How to properly include Header and Implementation Files?

I am a novice programmer in c++, and I am currently getting a compiling error

Undefined symbols for architecture x86_64

Supposedly this originates from how the header files and implementation files are included/coded.

Below is some code that generates the compiling error I am receiving


Main

//Main.cpp
#include <iostream>
#include <string>
#include "Animal.hpp"

using namespace std;

int main(){
    Animal myPet;
    myPet.shout();

    return 0;
}

Header

//Animal.hpp
#ifndef H_Animal
#define H_Animal

using namespace std;

#include <string>

class Animal{
public:
    Animal();

    void shout();
private:
    string roar;
};
#endif

Implementation

//Animal.cpp
#include "Animal.hpp"
#include <string>

Animal::Animal(){
    roar = "...";
}

void Animal::shout(){
    roar = "ROAR";
    cout << roar;
}

This code generates my compiling issue. How would this issue be resolved?

Thanks for your time


EDIT

Undefined symbols for architecture x86_64:
  "Animal::shout()", referenced from:
      _main in test-5f7f84.o
  "Animal::Animal()", referenced from:
      _main in test-5f7f84.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Upvotes: 1

Views: 2654

Answers (3)

Micha
Micha

Reputation: 191

maybe you might want to see an alternative set of your 3 files, where things are a little more "sorted", you know, where things are put at places where they "really" belong to.

So here's the "new" header file ..

//Animal.hpp
#ifndef H_Animal
#define H_Animal

#include <string> // suffices

// Interface.
class Animal {
    std::string roar; // private

public:
    Animal();
    void shout();
};

#endif

then the source file ..

//Animal.cpp
#include "Animal.hpp"

#include <iostream> // suffices

// Constructor.
Animal::Animal()
    :
    roar("...") // data member initializer
{}

// Member function.
void Animal::shout() {
    roar = "ROAR";
    std::cout << roar;
}

and the main program ..

//Main.cpp
#include "Animal.hpp"

int main(){
    Animal thePet;
    thePet.shout(); // outputs: `ROAR'
}

plus a little GNU makefile ..

all: default run

default: Animal.cpp Main.cpp
    g++ -o Main.exe Animal.cpp Main.cpp

run:
    ./Main.exe

clean:
    $(RM) *.o *.exe

Kick-off things typing just "make" in your cmd-line. Did you like it? -- Regards, M.

Upvotes: 2

Nicholas Hayden
Nicholas Hayden

Reputation: 523

The main issue I was having with this coding project was solved by @JamesMoore.

"@Nicholas Hayden Okay if you have three files, test.cpp(which has main), animal.cpp, and animal.hpp. The command should be g++ animal.cpp test.cpp. You need to compile all source files."

I am currently not using an IDE. So, when I was calling the compiler to compile my main.cpp - It was an issue of compiling the implementation file.

g++ test.cpp

needed to become

g++ test.cpp animal.cpp

This would call the compiler to compile everything the program needed.

Upvotes: 1

5gon12eder
5gon12eder

Reputation: 25419

I can only find one error in your code and your compiler should have told you that one.

In Animal.cpp, you are using std::cout but you're not #includeing <iostream>. You #include it in Main.cpp but it is not needed there.

If you (really) want to refer to std::cout as cout in Animal.cpp, you also have to add a using namespace std directive in that file.

The using directive in the header file (Animal.hpp) is evil. Get rid of it and type std::string instead. Putting using directives into headers litters the namespaces of all files that use it.

I also don't understand your intentions with the roar member. What is the point of assigning "..." to it in the constructor and re-assigning "ROAR" to it every time shout is called? Couldn't you do without that variable and simply have

void
Animal::shout()
{
  std::cout << "ROAR\n";
}

? I have added a newline because you'd probably want one.

Upvotes: 1

Related Questions