I'm working on my first large C++ project, and I'm having huge problems getting it to build corectly.
first of all, the errors:
/tmp/ccn7hjru.o: In function `match(std::basic_istream<char, std::char_traits<char> >&, char const*)':
Geometry.cpp:(.text+0x0): multiple definition of `match(std::basic_istream<char, std::char_traits<char> >&, char const*)'
/tmp/ccfuS3Jb.o:Camera.cpp:(.text+0x0): first defined here
/tmp/ccn7hjru.o: In function `eat(std::basic_istream<char, std::char_traits<char> >&)':
Geometry.cpp:(.text+0xda): multiple definition of `eat(std::basic_istream<char, std::char_traits<char> >&)'
/tmp/ccfuS3Jb.o:Camera.cpp:(.text+0xda): first defined here
/tmp/ccIOhdcQ.o: In function `match(std::basic_istream<char, std::char_traits<char> >&, char const*)':
Light.cpp:(.text+0x0): multiple definition of `match(std::basic_istream<char, std::char_traits<char> >&, char const*)'
/tmp/ccfuS3Jb.o:Camera.cpp:(.text+0x0): first defined here
/tmp/ccIOhdcQ.o: In function `eat(std::basic_istream<char, std::char_traits<char> >&)':
Light.cpp:(.text+0xda): multiple definition of `eat(std::basic_istream<char, std::char_traits<char> >&)'
/tmp/ccfuS3Jb.o:Camera.cpp:(.text+0xda): first defined here
....
this goes on for hundreds of lines
All of my c++ course files look like this:
#include "Camera.h"
#include "util.h"
Camera::Camera() {
// TODO Auto-generated constructor stub
}
Camera::Camera(int x, int y) {
this->resX = x;
this->resY = y;
}
Camera::~Camera() {
// TODO Auto-generated destructor stub
}
...more class methods below...
and the header files all look like this:
#ifndef CAMERA_H_
#define CAMERA_H_
#include "SceneElement.h"
#include "P3D.h"
#include "Ray.h"
#define CAMERA_PRE "{CAM:"
#define CAMERA_POST ":CAM}"
#define TAG_LOCATION "LOC:"
#define TAG_PLANE "PLANE:"
#define TAG_UPPER_RIGHT "UR:"
#define TAG_UPPER_LEFT "UL:"
#define TAG_LOWER_RIGHT "LR:"
#define TAG_LOWER_LEFT "LL:"
#define TAG_RES_X "RESX:"
#define TAG_RES_Y "RESY:"
class Camera: public SceneElement {
public:
P3D location;
P3D upperLeft;
P3D upperRight;
P3D lowerLeft;
P3D lowerRight;
int resX, resY;
Camera();
Camera(int, int);
virtual ~Camera();
virtual void toStream(std::ostream &);
virtual void fromStream(std::istream &);
Ray getRay(int, int);
};
#endif /* CAMERA_H_ */
the one exception is a util file, which looks like this:
#include "util.h"
#include <iostream>
#include <stdlib.h>
#include <string.h>
void match(std::istream &str, const char* expected){
int len = strlen(expected);
char* fromStream = (char*)malloc(len+1);
str.read(fromStream, len);
fromStream[len] = 0;
if(strcmp(fromStream, expected)){
std::cout << "expected " << expected << ", got " << fromStream << "\n";
free(fromStream);
exit(1);
}
free(fromStream);
}
void eat(std::istream &str){
char c;
while(c=str.peek(), c == ' ' || c == '\n' || c == '\t'){
str.get();
}
}
with a header file that looks like this:
#ifndef UTILS
#define UTILS
#include <iostream>
void match(std::istream &str, const char* expected);
void eat(std::istream &str);
#endif
Look into SceneElement.h, P3D.h and Ray.h. Most likely, you have included util.cpp in one of these header files.
Another possibility could be a definition of match() and eat() in one of the header files.
Related
I would like to be able to use a generic string parsing function as follows:
Utils::parse::fromString<int>(whatever)
Utils::parse::fromString<float>(whatever)
Following the suggestion here, I moved template specialization to separate *.ipp files, which are #includeed from the *.hpp:
Utils.hpp
#ifndef UTILS_HPP_
#define UTILS_HPP_
#include <string>
namespace Utils
{
namespace parse
{
template<typename T>
T fromString(std::string s);
}
}
#include "Utils.ipp"
#endif // UTILS_HPP_
Utils.ipp
#ifndef UTILS_IPP_
#define UTILS_IPP_
template<>
int Utils::parse::fromString<int>(std::string s) { return 42; }
template<>
float Utils::parse::fromString<float>(std::string s) { return 42.0; }
#endif // UTILS_IPP_
Now I have a class with a specialized method:
Foo.hpp
#ifndef FOO_HPP_
#define FOO_HPP_
#include <string>
#include "Utils.hpp"
class Foo
{
public:
Foo();
template<typename T>
T get(std::string s);
};
#include "Foo.ipp"
#endif // FOO_HPP_
Foo.ipp
#ifndef FOO_IPP_
#define FOO_IPP_
#include <string>
template<typename T>
T Foo::get(std::string s)
{
return Utils::parse::fromString<T>(s);
}
#endif // FOO_HPP_
test.cpp
#include <iostream>
#include <string>
#include "Utils.hpp"
#include "Foo.hpp"
// Custom template specialization
template<>
char Utils::parse::fromString<char>(std::string s)
{
return 'c';
}
int main()
{
// Calling `fromString` directly - this works!
const std::string whatever = "whatever";
std::cout << Utils::parse::fromString<int>(whatever) << std::endl;
std::cout << Utils::parse::fromString<char>(whatever) << std::endl;
// Calling `fromString` via `Foo` - linking error!
Foo foo;
std::cout << foo.get<int>(whatever) << std::endl;
return 0;
}
If I only use fromString directly, it works fine. However, if I use Foo, i get "multiple definition" linking errors:
g++ test.cpp Foo.cpp
/tmp/cc7ACcVe.o: In function `int Utils::parse::fromString<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
Foo.cpp:(.text+0x0): multiple definition of `int Utils::parse::fromString<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
/tmp/ccrN171X.o:test.cpp:(.text+0x0): first defined here
/tmp/cc7ACcVe.o: In function `float Utils::parse::fromString<float>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
Foo.cpp:(.text+0xf): multiple definition of `float Utils::parse::fromString<float>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
/tmp/ccrN171X.o:test.cpp:(.text+0xf): first defined here
collect2: error: ld returned 1 exit status
Whereas template functions doesn't require inline to avoid multiple definitions, specialization does as regular functions.
You have to add it:
template <>
inline int Utils::parse::fromString<int>(std::string s) { return 42; }
template<>
inline float Utils::parse::fromString<float>(std::string s) { return 42.0; }
Through the act of separating a set of input and output related functions from other parts of a program, I have encountered a problem with compiling files when functions in a header are placed within a namespace. The following files compile:
main.cpp
#include "IO.h"
int main()
{
testFunction("yikes");
}
IO.h
#ifndef IO_H_INCLUDED
#define IO_H_INCLUDED
#include <string>
void testFunction(const std::string &text);
#endif
However, when testFunction is placed in a namespace:
#ifndef IO_H_INCLUDED
#define IO_H_INCLUDED
#include <string>
// IO.h
namespace IO
{
void testFunction(const std::string &text);
}
#endif
within IO.h, and then invoked as IO::testFunction, compilation fails, throwing
undefined reference to `IO::testFunction(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2.exe: error: ld returned 1 exit status`
In each case, IO.cpp is
#include <string>
#include <iostream>
void testFunction(const std::string &text)
{
std::cout << text << std::endl;
}
and the compilation command is g++ -std=c++11 main.cpp IO.cpp, with the compiler being x86_64-w64-mingw32 from TDM-GCC, on Windows 10 Home.
If you change the declaration of your function to be in a namespace you need to implement the function within this namespace aswell.
The signature of your function will be IO::testFunction(...) but you only implemented testFunction(...) so there is no implementation for IO::testFunction(...)
The header file (IO.h):
namespace IO {
void testFunction(const std::string &text);
}
The cpp file (IO.cpp):
#include "IO.h"
// either do this
namespace IO {
void testFunction(const std::string &text) { ... }
// more functions in namespace
}
// or this
void IO::testFunction(const std::string &text) { ... }
I have the following header file (Student.h)
#ifndef STUDENT_H_
#define STUDENT_H_
#include <string>
using namespace std;
class Student {
int id;
string name;
string school;
public:
/*
* Default ctor
*/
Student();
/*
* Overloaded ctor
*/
Student(int id, string name, string school);
/*
* Compares two students by ID for equality
*/
bool operator == (const Student& other) const;
/*
* Compares two students by ID for ordering
*/
bool operator < (const Student& other) const;
};
#endif /* STUDENT_H_ */
And here is my implementation (in another file called Student.cpp):
#include "Student.h"
#include <string>
using namespace std;
bool Student::operator==(const Student& other) const{
return(Student::id == other.id);
}
bool Student::operator<(const Student& other) const{
return(Student::id < other.id);
}
And then finally a main.cpp file which references both files:
#include "Student.h"
#include "Student.cpp"
#include <iostream>
using namespace std;
int main() {
bool equal;
Student s1(111, "Jeff", "Rockywood High");
Student s2(100, "Bobby", "Carmel High");
equal = (s1==s2);
cout << equal;
}
I am getting an error from xcode telling me that:
the Undefined symbols for architecture x86_64:
Student::Student(int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
By placing #include "Student.cpp" in the Student.cpp file I had included the same file twice, without realizing it. Thus, Student::Student was defined twice...and thus the duplicate symbol error.
My C program application needs to call C++ function . But there is string type in C++ function . For example ,I need to write a function fooC() like this:
//main.c:
void fooC()
{
char* str = "hello";
fooCPP(str);
}
//foo.cpp
void fooCPP(String& str)
{
......
}
How to write code correctly?
update
//hello.cpp
#include <iostream>
#include <string>
#include "hello.h"
using namespace std;
void fooCpp(char const* cstr){
std::string str(cstr);
cout << str <<endl;
}
//hello.h
#ifdef __cplusplus
extern "C"{
#endif
void fooCpp(char const* str);
#ifdef __cplusplus
}
#endif
//main.c
#include "hello.h"
int main()
{
char* str = "test" ;
fooCpp(str);
return 0;
}
compile:
g++ -c hello.cpp hello.h
gcc hello.o main.c -g -o main
error :
hello.o: In function __static_initialization_and_destruction_0(int, int)':
hello.cpp:(.text+0x23): undefined reference tostd::ios_base::Init::Init()'
hello.o: In function __tcf_0':
hello.cpp:(.text+0x6c): undefined reference tostd::ios_base::Init::~Init()'
hello.o: In function fooCpp':
hello.cpp:(.text+0x80): undefined reference tostd::allocator::allocator()'
hello.cpp:(.text+0x99): undefined reference to std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)'
hello.cpp:(.text+0xa4): undefined reference tostd::allocator::~allocator()'..............................
....................................
Nope. You need to write a wrapper in C++:
//foo.cpp
void fooCPP(std::string& str)
{
......
}
extern "C" void fooWrap(char const * cstr)
{
std::string str(cstr);
fooCPP(str);
}
And call it from C:
/*main.c:*/
extern void fooWrap(char const * cstr); /*No 'extern "C"' here, this concept doesn't exist in C*/
void fooC()
{
char const* str = "hello";
fooWrap(str);
}
I am creating an interface called Index that will allow me to Index using either a hash table or a AVL tree. I am getting the following error:
Undefined symbols for architecture x86_64:
"IndexHash::IndexHash(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)", referenced from:
_main in main.o
"IndexHash::IndexHash()", referenced from:
Parser::createIndex() in Parser.o
These are coming from the lines:
Index* mainIn;
// creates a new index pointer
if (indexType_ == 1) {
mainIn = new IndexAVL();
} else if (indexType_ == 2) {
mainIn = new IndexHash();
}
This worked when it was just the AVL tree.
Index.H
#ifndef INDEX_H
#define INDEX_H
#include <iostream>
#include <fstream>
#include <vector>
#include "WordEntry.h"
#include "Document.h"
class Index {
public:
virtual WordEntry* search(WordEntry*&)=0;
virtual void insert(WordEntry*&)=0;
virtual void insert(string)=0;
virtual void printOut(ofstream&)=0;
virtual void createDocument(string, string, string)=0;
virtual int getNumberDocs()=0;
virtual void trim(string&)=0;
private:
};
#endif
IndexHash.h
#ifndef INDEXHASH_H
#define INDEXHASH_H
#include <iostream>
#include <fstream>
#include <vector>
#include "WordEntry.h"
#include "IndexHash.h"
#include "Document.h"
#include <tr1/unordered_map>
class IndexHash : public Index{
public:
IndexHash();
IndexHash(string);
IndexHash(const IndexHash&);
~IndexHash();
virtual WordEntry* search(WordEntry*&);
virtual void insert(WordEntry*&);
virtual void insert(string);
virtual void printOut(ofstream&);
virtual int getNumberDocs();
virtual void trim(string&);
virtual void createDocument(string, string, string);
int searchDocs(string);
Document* binarySearch(vector<Document*>*, int, int, int);
void quickSort(vector<Document*>*, int, int);
private:
tr1::unordered_map< WordEntry*, vector<Document*> >* hashtable_;
vector<Document*>* seenDocs;
};
#endif /* INDEXHASH_H */
IndexHash.cpp
#include "IndexHash.h"
#include "Document.h"
#include <vector>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <istream>
using namespace std;
IndexHash::IndexHash() {
hashtable_ = new tr1::unordered_map< WordEntry*, vector<Document*> >;
seenDocs = new vector<Document*>;
}
... it defines everything, it is just hard for me to copy and paste it in here and I am assuming the problems is in includes.