0

I've been doing C programming for uni and in my spare time I'm moving onto c++ and am trying to start with classes in seperate files and whatnot, but I'm getting some problems when trying to make my project. I'm using the following makefile

EXEC = main
OBJS = main.o Bunny.o Name.o Board.o
CC = g++

CFLAGS = -Wall -Wextra -Werror
LIBS = 
LDFLAGS = 


$(EXEC): $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)



.PHONY: clean

clean: 
    rm -f $(EXEC) $(OBJS) 
run:
    ./$(EXEC)

Which is just an altered version of my C one so it might be that, and here are the relevant other files

main.cpp

#include <iostream>

#include "Name.hpp"
#include "definitions.hpp"

int main() {

    Name nameContainer;

    nameContainer.initMaleNameValidArray(); 

    std::cout << "Got to just before the return!\n" << std::endl;

    return 0;
}

Name.cpp

#include <iostream>
#include <fstream>
#include <string>
#include "definitions.hpp"

class Name{
    public:
        void initFemaleNameArray() {
            std::ifstream myReadFile;
            myReadFile.open("girlsnames.txt");
            char output[100];
            if (myReadFile.is_open()) {
                while (!myReadFile.eof()) {
                    myReadFile >> output;
                    std::cout<<output;
                }
            }
            myReadFile.close();
        }

        void initMaleNameArray() {

        }

        void initFemaleNameValidArray() {
            static int femaleValidArray[GIRLS_NAMES] = {0};
        }

        void initMaleNameValidArray() {
            static int MaleValidArray[GIRLS_NAMES] = {0};
        }

        void freeAFemaleName(std::string name);

        void freeAMaleName(std::string name);

        std::string returnFreeFemaleName();

        std::string returnFreeMaleName();

    private:
        std::string femaleNameArray[GIRLS_NAMES];

        std::string maleNameArray[BOYS_NAMES];

        int femaleValidArray[GIRLS_NAMES];

        int maleValidArray[BOYS_NAMES];
};

Name.hpp

#ifndef NAME_HPP
#define NAME_HPP

#include "definitions.hpp"

class Name{
    public:
        void initFemaleNameArray();

        void initMaleNameArray();

        void initFemaleNameValidArray();

        void initMaleNameValidArray();

        void freeAFemaleName(std::string name);

        void freeAMaleName(std::string name);

        std::string returnFreeFemaleName();

        std::string returnFreeMaleName();

    private:
        std::string femaleNameArray[GIRLS_NAMES];

        std::string maleNameArray[BOYS_NAMES];

        int femaleValidArray[GIRLS_NAMES];

        int maleValidArray[BOYS_NAMES];
};

#endif

And the error im getting when running make is:

mark@Mark-Linux:~/Documents/Misc/C++/Bunny$ make
g++    -c -o main.o main.cpp
g++    -c -o Bunny.o Bunny.cpp
g++    -c -o Name.o Name.cpp
g++    -c -o Board.o Board.cpp
g++  -o main main.o Bunny.o Name.o Board.o 
main.o: In function `main':
main.cpp:(.text+0x26): undefined reference to `Name::initFemaleNameArray()'
collect2: ld returned 1 exit status
make: *** [main] Error 1

At the moment I'm just trying to see if I can use a method from a class in a different file hence the incompleteness of the code.

Sorry about the wall of text but I'm well and truly stumped, so if anyone could offer any advice that'd be greatly appreciated.

1
  • Not related to your question, but ... you want CXX=g++ and CXXFLAGS== -Wall -Wextra -Werror in your makefile. Commented Oct 16, 2012 at 13:27

2 Answers 2

3

In name.hpp you are defining the Name class, and that is ok. But in name.cpp you are defining that class again. Which is not what you want. You should have name.cpp implement the functions. That would look something like this:

#include <iostream>
#include <fstream>
#include <string>
#include "definitions.hpp"

#include "name.hpp"

void Name::initFemaleNameArray() {
    std::ifstream myReadFile;
    myReadFile.open("girlsnames.txt");
    char output[100];
    if (myReadFile.is_open()) {
        while (!myReadFile.eof()) {
            myReadFile >> output;
            std::cout<<output;
        }
    }
    myReadFile.close();
}

void Name::initMaleNameArray() {}

void Name::initFemaleNameValidArray() {
    // This is wrong, too. This creates a new array
    //static int femaleValidArray[GIRLS_NAMES] = {0};
    // You want this:
    memset(femaleValidArray, 0, sizeof(femaleValidArray));
}

void Name::initMaleNameValidArray() {
    //static int MaleValidArray[GIRLS_NAMES] = {0};
    memset(MaleValidArray, 0, sizeof(MaleValidArray));
}

void Name::freeAFemaleName(std::string name) {}
void Name::freeAMaleName(std::string name) {}
std::string Name::returnFreeFemaleName() {}
std::string Name::returnFreeMaleName() {}
Sign up to request clarification or add additional context in comments.

Comments

1

Your Name.cpp and Name.hpp are actually declaring separate classes, which is probably undefined behaviour. Instead your Name.cpp should look like this:

#include <iostream>
#include <fstream>
#include <string>
#include "Name.hpp"

void Name::initFemaleNameArray() {
    std::ifstream myReadFile;

etc.

4 Comments

The answer is of course correct, but it's no undefined behaviour, since he doesn't include Name.hpp in Name.cpp, so it's really two different classes in two different TUs, which is perfectly valid, though not what he wants.
@ChristianRau - I disagree. Having distinct classes with the same name in separate translation units violates the one-definition-rule.
C++11, draft n3290, §3.2/5, "There can be more than one definition of a class type … provided that each definition appears in a different translation unit, and provided … each definition … shall consist of the same sequence of tokens …"
@Robᵩ Ah, seems you're right. Annonymous namespaces to the rescue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.