koleS
koleS

Reputation: 1313

Multiple definition of C++. How to split C++ program properly?

I wrote a program that works without problems, but the thing I am afraid of is that I get a lot of warnings, when I compile it with -Wall option ( it's program written in C and C++). Actually there is only one type of warning, but occurs many times : Multiple definition of .... ( contructors , destructors, and functions ). I thought I did it correcly, but obviously I am wrong. I have 9 files:

Server.h     
Server.cpp - implements methods declared in Server.h

RankingCreator.h
RankingCreator.cpp - implements methods declared in RankingCreator.h

Parser.h
Parser.cpp - implements methods declared in Parser.h

PageHandler.h
PageHandler.cpp - implements methods declared in PageHandler.h

and

Main.cpp 

- all header files are included in this file, because I use and combine functionality of all classes here

Each .cpp file except Main.cpp contains only one corresponding .h file included, for instance Server.cpp contains #include "server.h" and no more .h/.cpp files listed above ( but it does contain headers like stdio.h and string.h ). I can post whole warning message here and code of classes, but the lenght of error is about 50 lines, and all classes would be about 1000 lines, so tell me if it is really needed to solve this. Any idea how to solve this? Do I have to make every function inline or something? Every header file has #if def block at the beginning.

EDIT: Here is the warning log :

g++ LearnTidyCurl.cpp MyParser.cpp PageHandler.cpp RankingCreator.cpp Server.cpp -lcurl -ltidy -o -Wall Wynik

Here is code of one of my header files, see the way of ifdefs :

#ifndef RANKINGCREATOR_H_
#define RANKINGCREATOR_H_


#include <stdio.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <algorithm>

//using namespace std;

struct rankingElement {
    std::string url;
    int rank;
    bool operator() (rankingElement i, rankingElement j) { return (i.rank >     j.rank);}

}  ;

bool operator==(const rankingElement& elem, const std::string& url);

class RankingCreator {
public:
    rankingElement compareRankingElements;
    const static int MAX_QUERY_RESULT_SIZE = 20;
    RankingCreator();
    virtual ~RankingCreator();
    bool checkPageRank( rankingElement rElement,  std::vector<rankingElement> &ranking );
    void insertIntoRanking( rankingElement rElement,  std::vector<rankingElement>& ranking);

};

#endif /* RANKINGCREATOR_H_ */

I threw warning message out, because it makes this topic unreadable. Btw. I use include guards auto-generated by Eclipse - shouldn't they be just fine? ( When creating a new class they are automatically created )

EDIT:

You can download gedit file with error log here :

http://www4.zippyshare.com/v/62324366/file.html

I didn't want to post 105-lined error here and in addition it is in crap format, so would not good look here.

Server.h :

#ifndef SERVER_H_
#define SERVER_H_

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <sstream>
#include <vector> 

...body...

#endif /* SERVER_H_ */

PageHandler.h

#ifndef PAGEHANDLER_H_
#define PAGEHANDLER_H_

#include <tidy.h>
#include <buffio.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
#include <string.h>
#include <curl/curl.h>
#include <vector>
#include <algorithm>
#include <stdexcept>

... body ...

#endif /* PAGEHANDLER_H_ */

MyParser.h

#ifndef MYPARSER_H_
#define MYPARSER_H_

#include <vector>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <algorithm>
#include <queue>
#include <stdlib.h>

...body...

#endif /* MYPARSER_H_ */

Main.cpp

#include <stdio.h>
#include <iostream>
#include <queue>
#include "MyParser.h"
#include "PageHandler.h"
#include "RankingCreator.h"
#include "Server.h"

#define NO_ERROR 0

std::string convertIntToString(int input) {

    std::ostringstream ss;
    ss << input;
    std::string tmpStr = ss.str();

return tmpStr;
}

int main(int argc, char **argv) {

... body ...
return 0;
}

MyParser.cpp

#include "MyParser.h"

PageHandler.cpp

#include "PageHandler.h"

Server.cpp

#include "Server.h"

RankingCreator.cpp

#include "RankingCreator.h"

Upvotes: 0

Views: 1685

Answers (2)

aayoubi
aayoubi

Reputation: 12069

Write your header files the following way:

#ifndef SERVER_H
#define SERVER_H
//...
#endif

They are called #include guards to avoid double inclusion problems. Read about them here

If you are ever developing on MVSC++, you can use #pragma once as a first line of each header, but the first solution is portable on every platform.

Upvotes: 0

John Humphreys
John Humphreys

Reputation: 39224

Change your inclusion guards:

#ifndef FILENAME_H
#define FILENAME_H

//Code

#endif

And I bet your problem goes away. Obviously make sure each FILENAME_H is unique :) And remember - each header needs this around all it's code, but it shouldn't be in your source files.

Upvotes: 1

Related Questions