C++ - Getting undefined reference to my class - c++

I have tried to find a solution to my problem online, but I've been unsuccessful. I think my problem may be related to linking.
I have 3 files scanner.h , scanner.cpp and scanner_test.h I've trimmed the files as best I can.
scanner.h
class Scanner {
public:
Token *scan (const char *);
};
scanner.cpp
#include "scanner.h"
Token scan(const char *text){
// Do something code
}
scanner_test.h
#include "scanner.h"
Scanner *s ;
void test_setup_code ( ) {
s = new Scanner() ;
}
Token *tks = s->scan ( text ) ; //This line gives the error
The error when I try to compile and run is from scanner_test.h undefined reference to `Scanner::scan(char const*)
This is my understanding of the code:
scanner_test.h includes the scanner.h file which is linked to scanner.cpp during compilation and this file has the definition for Scanner::scan(char const*)

In scanner.cpp, you need:
Token* Scanner::scan(const char *text) { ... }
// ^^^^^^^^^
otherwise you are implementing a free function called scan, not the member method from Scanner. (Note I also added the * you were missing, but the compiler will tell you this anyways once you added the Scanner:: part)

Related

linking hpp and cpp issues with g++ compiler

I am relatively new to c++ and have a solid C and Object Oriented background. So I have the following code written.
I have Person.hpp which is as follows:
class Person
{
private:
struct h
{
char *name;
unsigned char age;
};
struct h entities;
public:
unsigned char age();
char *name();
Person(char *name, unsigned char a);
~Person();
};
The Person.cpp looks as follows:
#include "Person.hpp"
char *Person::name()
{
return entities.name;
}
unsigned char Person::age()
{
return entities.age;
}
Person::Person(char *name, unsigned char a)
{
entities.name = name;
entities.age = a;
}
And finally main.cpp looks like the following:
#include <iostream>
#include "Person.hpp"
int main()
{
Person someone("something", 100);
printf("%s is %d old\n", someone.name(), someone.age());
return 0;
}
I am already aware of the warning that it will cause due to the fact that the string is not constant. This will not cause an error when trying to compile. I tried compiling the code in two different methods. One by just compiling all together which would look like the following:
g++ -o main main.cpp Person.cpp
And the second method I tried was to compile them into object files and then link them together:
g++ -c main.cpp
g++ -c Person.cpp
g++ -o main main.o Person.o
They both give the following error:
/usr/bin/ld: main.o: in function `main':
main.cpp:(.text+0x5b): undefined reference to `Person::~Person()'
/usr/bin/ld: main.cpp:(.text+0x6e): undefined reference to `Person::~Person()'
collect2: error: ld returned 1 exit status
Any help would be greatly appreciated.
You have a destructor declared here in your header file:
public:
unsigned char age();
char *name();
Person(char *name, unsigned char a);
~Person(); // <===== Declared here
But you haven't provided any definitions for it.
However, the destructor is called after your main function returns (you can learn more about this behavior here), so it needs a definition.
You can make the compiler generate the definition for you by either omitting the destructor declaration or use ~Person() = default.
The problem is that you declare both an constructor and destructor in Person.hpp, but only define the constructor in the Person.cpp file.
Try add the following code to Person.cpp:
Person::~Person()
{
}

Trying to implement a basic class in C++

I'm learning C++ and currently trying to create a very basic class representing a boat's length and weight... It seems I'm running into problems trying to split it into header and cpp files.
These are the simple files I'm working with...
Boat.h:
#ifndef BOAT_H_
#define BOAT_H_
class Boat{
public:
Boat();
Boat(int,int);
private:
int length;
int weight;
};
#endif /* BOAT_H_ */
Boat.cpp:
#include "Boat.h"
Boat::Boat(){
length = 25;
weight = 2500;
}
Boat::Boat(int newLength, int newWeight){
length = newLength;
weight = newWeight;
}
When compiling, I get errors in Boat.cpp about it being "first defined here". I've been following tutorials and trying to do like they do but I just can't seem to get this right. Here is the full error message. What am I missing?
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:4: multiple definition of `Boat::Boat()'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:4: first defined here
Boat.o: In function `Boat':
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:4: multiple definition of `Boat::Boat()'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:4: first defined here
Boat.o: In function `Boat':
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:9: multiple definition of `Boat::Boat(int, int)'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:9: first defined here
Boat.o: In function `Boat':
C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/../Boat.cpp:9: multiple definition of `Boat::Boat(int, int)'
Main.o:C:\Documents and Settings\Administrateur\Bureau\Workspace\ClassTests\Debug/..//Boat.cpp:9: first defined here
Edit :
I was including Boat.cpp in the main instead of Boat.h... Problem solved! Thank you!
There is no way to be sure what you did, but I did manage to generate your error with this main function:
#include "Boat.h"
#include "Boat.cpp"
int main(int argc, const char *argv[])
{
Boat b;
return 0;
}
compiled in the following way:
g++ -O0 -ggdb main.cpp Boat.cpp -o main
which results exactly in the error you reported. Whatever you did - you seem to have tried to include the Boat.cpp file twice, and by doing so, you have doubled the definition of your Boat class.
It seems that you included your boat.cpp file in the module where there is function main. You need to include only header boat.h in the module with main.

Duplicate symbols only for iOS simulator build

I'm having a strange issue when compiling an open source library. When compiling for the device, Xcode compiles it just fine and deploys it no problem. However, when I compile for the simulator, I get duplicate symbol errors during the linking phase.
I've checked a few of these out, and it seems these symbols were all implemented in the .hh file as opposed to the .m file. Obviously this is bad code structure, and the errors make sense. However, what doesn't make sense is why there are no errors for the device build.
Each of these .hh files contains #pragma once at the top of the file. My initial thought was that this wasn't working as expected, but upon removal I get compile-time errors for both device and simulator builds stating I've redefined these symbols. Hmm, so I then tried replacing #pragma once with
#ifndef EXAMPLE_DEFINE
#define EXAMPLE_DEFINE
// code
#end if
But this yields identical results to the #pragma once.
Due to the sheer number of code changes that would be required, it isn't feasible for me to go through and fix every error manually, especially since I'll want to be able to update the codebase easily. So is there any reason this is not failing for the device, and how I could make simulator builds perform the same way?
EDIT: I've also tested using #import instead of #include, but it too yields the same results
EDIT 2: After more testing, I've found that if I define a Preprocessor macro in the target's build settings, the code inside the #ifndef never gets called, as is expected. For whatever reason, it looks like defining the new definition in the .hh file isn't being carried over into the next compilation of the file.
Also, as requested, here's an excerpt from the build log
duplicate symbol __ZZN12DelegateFuncIFvR16DualTextMenuItemRKN5Input5EventEEEC1IZN25MultiChoiceSelectMenuItem4initEPPKciiibSB_P12ResourceFaceEUlS1_S5_E_EERKT_PNSt3__19enable_ifIXntsr3std11is_functionISG_EE5valueEvE4typeEENKS8_ISF_EUlRKNS7_7StorageES1_S5_E_cvPFvSR_S1_S5_EEv in:
/Users/riley.testut/Library/Developer/Xcode/DerivedData/GBA4iOS-dqkflotukruucqbxjyslhtfuekse/Build/Intermediates/GBA4iOS.build/Debug-iphonesimulator/GBA4iOS.build/Objects-normal/i386/Main-FB93852047D42061.o
/Users/riley.testut/Library/Developer/Xcode/DerivedData/GBA4iOS-dqkflotukruucqbxjyslhtfuekse/Build/Intermediates/GBA4iOS.build/Debug-iphonesimulator/GBA4iOS.build/Objects-normal/i386/OptionView.o
duplicate symbol __ZZN12DelegateFuncIFbiRKN5Input5EventEEEC1IZN15MultiChoiceView4initER19MultiChoiceMenuItemb9_2DOriginEUliS3_E_EERKT_PNSt3__19enable_ifIXntsr3std11is_functionISC_EE5valueEvE4typeEENKS6_ISB_EUlRKNS5_7StorageEiS3_E_cvPFbSN_iS3_EEv in:
/Users/riley.testut/Library/Developer/Xcode/DerivedData/GBA4iOS-dqkflotukruucqbxjyslhtfuekse/Build/Intermediates/GBA4iOS.build/Debug-iphonesimulator/GBA4iOS.build/Objects-normal/i386/Main-FB93852047D42061.o
/Users/riley.testut/Library/Developer/Xcode/DerivedData/GBA4iOS-dqkflotukruucqbxjyslhtfuekse/Build/Intermediates/GBA4iOS.build/Debug-iphonesimulator/GBA4iOS.build/Objects-normal/i386/OptionView.o
duplicate symbol __ZZN12DelegateFuncIFvR12TextMenuItemRKN5Input5EventEEEC1IN14YesNoAlertView2noMUlS1_S5_E_EEERKT_PNSt3__19enable_ifIXntsr3std11is_functionISB_EE5valueEvE4typeEENKS8_ISA_EUlRKNS7_7StorageES1_S5_E_cvPFvSM_S1_S5_EEv in:
/Users/riley.testut/Library/Developer/Xcode/DerivedData/GBA4iOS-dqkflotukruucqbxjyslhtfuekse/Build/Intermediates/GBA4iOS.build/Debug-iphonesimulator/GBA4iOS.build/Objects-normal/i386/ButtonConfigView.o
/Users/riley.testut/Library/Developer/Xcode/DerivedData/GBA4iOS-dqkflotukruucqbxjyslhtfuekse/Build/Intermediates/GBA4iOS.build/Debug-iphonesimulator/GBA4iOS.build/Objects-normal/i386/MenuView.o
ld: 16 duplicate symbols for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
and here's one of the offending files (AlertView.hh):
#pragma once
#include <gui/View.hh>
#include <gui/MenuItem/MenuItem.hh>
#include <util/gui/BaseMenuView.hh>
#include <util/rectangle2.h>
#include <util/DelegateFunc.hh>
class AlertView : public View
{
public:
constexpr AlertView() { }
Rect2<GC> labelFrame;
Gfx::Text text;
BaseMenuView menu;
Rect2<int> rect;
Rect2<int> &viewRect() { return rect; }
void init(const char *label, MenuItem **menuItem, bool highlightFirst);
void deinit() override;
void place() override;
void inputEvent(const Input::Event &e) override;
void draw(Gfx::FrameTimeBase frameTime) override;
};
class YesNoAlertView : public AlertView
{
public:
YesNoAlertView() { }
typedef DelegateFunc<void (const Input::Event &e)> InputDelegate;
MenuItem *menuItem[2] = {nullptr};
// Optional delegates
InputDelegate &onYes() { return onYesD; }
InputDelegate &onNo() { return onNoD; }
void init(const char *label, bool highlightFirst, const char *choice1 = nullptr, const char *choice2 = nullptr)
{
yes.init(choice1 ? choice1 : "Yes"); menuItem[0] = &yes;
no.init(choice2 ? choice2 : "No"); menuItem[1] = &no;
assert(!onYesD);
assert(!onNoD);
AlertView::init(label, menuItem, highlightFirst);
}
void deinit() override
{
logMsg("deinit alert");
AlertView::deinit();
onYesD = {};
onNoD = {};
}
InputDelegate onYesD;
InputDelegate onNoD;
private:
TextMenuItem yes
{
[this](TextMenuItem &, const Input::Event &e)
{
auto callback = onYesD;
removeModalView();
if(callback) callback(e);
}
};
TextMenuItem no
{
[this](TextMenuItem &, const Input::Event &e)
{
auto callback = onNoD;
removeModalView();
if(callback) callback(e);
}
};
};
It shows you have tried the header guards but my suggestion is once you check for following
link.
http://en.wikipedia.org/wiki/Include_guard
http://c2.com/cgi/wiki?RedundantIncludeGuards
The update shows it is linker error for symbols and this is for the library you are using.

Multiple definition of class method

I have the file long_arithm.cpp:
#ifndef LONG_ARITHM.CPP
#define LONG_ARITHM.CPP
#include <iostream>
#include <list>
namespace long_arithm {
typedef signed char schar;
enum { error_char = 127 };
class longint {
public:
longint() : minusSign(0), array() { }
longint(int num) { fromInt(num); }
longint(std::string str) { fromString(str); }
longint(const longint& other) : minusSign(other.minusSign), array(other.array) { }
void fromInt(int num);
void fromString(std::string str);
protected:
schar digtochar(schar num);
schar chartodig(schar ch);
inline bool isDigit(schar ch) { /* code */ }
inline bool isSpaceChar(schar ch) { /* code */ }
private:
bool minusSign;
std::list<schar> array;
};
};
void long_arithm::longint::fromInt(int num) {
/* code */
}
void long_arithm::longint::fromString(std::string str) {
/* code */
long_arithm::schar long_arithm::longint::digtochar(schar num) {
/* code */
}
long_arithm::schar long_arithm::longint::chartodig(schar ch) {
/* code */
}
#endif
Now I'm trying build it, but I have errors (1st and 2nd lines - Eclipce header):
Building target: long_arithmetics
Invoking: Cross G++ Linker
g++ -o "long_arithmetics" ./long_arithm.o ./main.o
./main.o: In function `long_arithm::longint::fromInt(int)':
/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:153: multiple definition of `long_arithm::longint::fromInt(int)'
./long_arithm.o:/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:153: first defined here
./main.o: In function `long_arithm::longint::fromString(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:168: multiple definition of `long_arithm::longint::fromString(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
./long_arithm.o:/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:168: first defined here
./main.o: In function `long_arithm::longint::chartodig(signed char)':
/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:204: multiple definition of `long_arithm::longint::chartodig(signed char)'
./long_arithm.o:/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:204: first defined here
./main.o: In function `long_arithm::longint::digtochar(signed char)':
/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:188: multiple definition of `long_arithm::longint::digtochar(signed char)'
./long_arithm.o:/home/gxoptg/Документы/My works/Developing/C++/long_arithmetics/Debug/../long_arithm.cpp:188: first defined here
(Note, the line links (like :188) are broken, because I threw out a lot of commented lines of code.)
Why I have that errors and what I should correct? As good as I understand,
void fromInt(int num);
and others are 'pre-definitions', and I don't see any other definitions of that methods.
Thank you for help.
The functions that are defined outside of the class definition must either be moved to a source (.cpp) file or you must use the inline keyword at the front of them. Otherwise a copy of the function is placed into each source file that includes the header and marked as available to other modules, and the linker complains when there's more than one.
You say you included long_arithm.cpp in main. But you also compile it separately and then try to link the result with main.o. That's what causes the duplicates.
Looks like you didn't close the namespace definition and used its name inside the namespace for qualifying the function names, while defining them inside. Including this .cpp file inside other files may cause multiple definitions to occur inside different .cpp files, which cause the aforementioned problem.

C++ CppUnit Test (CPPUNIT_ASSERT)

I'm trying to do up a screen scraping assignment. My cpp works, but I don't know how to integrate my unit testing. I tried to do a bool check unit test for the file validity but it's giving me this error:
error: cannot call member function 'bool ScreenScrape::getFile()' without object
screenscrape.cpp:
#include "screenscrape.h"
using namespace std;
int main()
{
ScreenScrape ss;
int choice;
...
...
ss.matchPatternTest();
}
screenscrape.h:
class ScreenScrape
{
public:
ScreenScrape();
void parserTest(int choice);
void matchPatternTest();
void setIndexValue(string data, string IndexName);
void setIndexChange(string data);
void setIndexPercent(string data);
void setIndexDate(string data);
bool getFile();
private:
string IndexName;
string IndexValue;
string IndexChange;
string IndexPercent;
string IndexVID;
string IndexCID;
string IndexPID;
string IndexDate;
};
bool ScreenScrape::getFile()
{
string file1 = "yahoofinance.htm";
char* file2 = new char [file1.size()+1]; // parse file for c string conversion
strcpy(file2, file1.c_str()); // converts to c string
ifstream fin;
fin.open(file2);
if(fin.good())
return true;
else
return false;
}
screenscrapetest.cpp:
#include "screenscrapetest.h"
#include "screenscrape.h"
CPPUNIT_TEST_SUITE_REGISTRATION (ScreenScrapeTest);
void ScreenScrapeTest::fileTest()
{
CPPUNIT_ASSERT(ScreenScrape::getFile()); // test file validity
}
screenscrapetest.h:
#ifndef _SCREENSCRAPETEST_H
#define _SCREENSCRAPETEST_H
#include <cppunit/TestCase.h>
#include <cppunit/extensions/HelperMacros.h>
#include "screenscrape.h"
class ScreenScrapeTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE (ScreenScrapeTest);
CPPUNIT_TEST (fileTest);
CPPUNIT_TEST_SUITE_END ();
public:
void fileTest();
};
#endif
I tried to declare "ScreenScrape ss;" under screenscrapetest.h, use an object (ss) to call getFile() but it's giving me multiples of this error:
/home/user/NetBeansProjects/Assignment1/screenscrape.h:259: multiple definition of `ScreenScrape::getFile()'
I only want to check for file validity with unit testing. Any help will be appreciated.
Thanks in advance!
Regards,
Wallace
bool ScreenScrape::getFile() is not static, so cannot be called as a static function. You'll need to either (a) declare it as static or (b) create an instance of ScreenScrape and call getFile() from it.
Looking at the code, it's not obvious why this function is a method of the class but perhaps it's still in the early stages of development. It can also be refactored to remove lots of redundant code:
bool ScreenScrape::getFile()
{
std::ifstream fin("yahoofinance.htm");
return fin.good();
}
Don't forget your include guards in screenscrape.h:
#ifndef SCREENSCRAPE_H
#define SCREENSCRAPE_H
// Class declaration here...
#endif//ndef SCREENSCRAPE_H
And consider moving the implementation of getFile to the cpp source file. These two steps will prevent you getting the "multiple declaration" errors.
This will fix your compilation errors, but checking for file validity is not a responsibility of a unit test. Unit tests should not interact with the filesystem.
If you're going to be calling ScreenScrape::getfile()rather than ss.getfile(), then getfile() needs be defined as static. The error you're getting is because non-static methods need to be called on a specific object.
It's difficult to track down the error with your version that defines a ScreenScrape object and then uses that to call getfile(); you obviously haven't included all the relevant code since your screenscrape.h file doesn't have 259 lines, and you also haven't shown the revised code in which you "use an object (ss) to call getFile()".