I have a C++ program with an undefined reference error on the call of a method in a class. As near as I can tell, the method is public and I'm calling it with a parameter declared the same as the method definition, but eclipse/gcc tells me it is undefined. I'm not used to C++, can someone please tell me what's wrong with the definition?
The main class:
#include <iostream>
using namespace std;
#include "AttenuationConfigurationTable.h"
int main()
{
flash_entry_struct flash_array[] = { { 10, 20, 30, 40 }, { 50, 60, 70, 80 }, { -1, -1, -1, -1 } };
// note: no undefined reference or any other error for the line with the class
AttenuationConfigurationTable attConfigTable;
// error appears for next line: undefined reference to ...load_attenuation_...
attConfigTable.load_attenuation_calibration_table_from_flash(flash_array);
return 0;
}
The class file:
#include "AttenuationConfigurationTable.h"
#include "flashEntryStruct.h"
AttenuationConfigurationTable::AttenuationConfigurationTable() { }
AttenuationConfigurationTable::~AttenuationConfigurationTable() { }
class Attenuation_configuration_table
{
struct attenuation_voltages_struct
{
float att_value;
float v1;
float v2;
} ;
struct frequency_tables_struct
{
int frequency;
attenuation_voltages_struct attenuation_voltages[100];
int voltages_count = 0;
} ;
frequency_tables_struct _frequency_tables[42];
public:
/************************************************************************/
/* load the table in this object from the given flash memory address */
/************************************************************************/
void load_attenuation_calibration_table_from_flash(flash_entry_struct memory_address[])
{
// bunch of logic here...
}
};
The h file for the class:
#ifndef ATTENUATIONCONFIGURATIONTABLE_H_
#define ATTENUATIONCONFIGURATIONTABLE_H_
#include "flashEntryStruct.h"
class AttenuationConfigurationTable
{
public:
AttenuationConfigurationTable();
virtual ~AttenuationConfigurationTable();
void load_attenuation_calibration_table_from_flash(flash_entry_struct flash_memory_address[]);
};
#endif /* ATTENUATIONCONFIGURATIONTABLE_H_ */
And, just for completeness, the h file defining the parameter structure:
#ifndef FLASHENTRYSTRUCT_H_
#define FLASHENTRYSTRUCT_H_
struct flash_entry_struct
{
uint16_t frequency;
uint16_t scaled_db;
int8_t v1_byte;
int8_t v2_byte;
} ;
#endif /* FLASHENTRYSTRUCT_H_ */
EDIT: the error message itself:
Invoking: Cygwin C++ Linker
g++ -o "HelloCPP.exe" ./src/AttenuationConfigurationTable.o ./src/Hello2.o ./src/HelloCPP.o
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: ./src/HelloCPP.o:/cygdrive/c/Users/ralph/files/programming/workspaces/HelloCPP/HelloCPP/Debug/../src/HelloCPP.cpp:15: undefined reference to `AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(flash_entry_struct*)'
collect2: error: ld returned 1 exit status
make: *** [makefile:58: HelloCPP.exe] Error 1
"make all" terminated with exit code 2. Build might be incomplete.
You declare AttenuationConfigurationTable in the header file with the load_attenuation_calibration_table_from_flash function, but then the function with the same name in the implementation file is inside the definition for another class, Attenuation_configuration_table.
Take the implementation for load_attenuation_calibration_table_from_flash out of the class definition for Attenuation_configuration_table in your cpp file, and define it instead as
void AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(/* ... */) {
// ...
}
This is the same syntax already used for the constructor and destructor in that file.
In the end, your header should look something like this:
class AttenuationConfigurationTable
{
public:
AttenuationConfigurationTable();
virtual ~AttenuationConfigurationTable();
void load_attenuation_calibration_table_from_flash(flash_entry_struct flash_memory_address[]);
private:
struct attenuation_voltages_struct
{
float att_value;
float v1;
float v2;
} ;
struct frequency_tables_struct
{
int frequency;
attenuation_voltages_struct attenuation_voltages[100];
int voltages_count;
} ;
frequency_tables_struct _frequency_tables[42];
};
and your cpp file should look something like this:
AttenuationConfigurationTable::AttenuationConfigurationTable() { }
AttenuationConfigurationTable::~AttenuationConfigurationTable() { }
void AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(/* params */) {
// body
}
Related
I'm coding a spreadsheet built up of column vectors and cell vectors, where
each cell is a placeholder for a cell value. CellValueBase is the base class, CellValue is the final template class.
This is the error:
g++ Cell.o Column.o sheet.o main.o -o spreadsheet
sheet.o: In function `CellValueBase::CellValueBase()':
sheet.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
sheet.o: In function `CellValueBase::CellValueBase()':
sheet.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
main.o: In function `CellValueBase::CellValueBase()':
main.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
main.o: In function `CellValueBase::CellValueBase()':
main.cc:(.text+0x0): multiple definition of `CellValueBase::CellValueBase()'
Column.o:Column.cc:(.text+0x0): first defined here
Cell.o: In function `CellValueBase::~CellValueBase()':
Cell.cc:(.text._ZN13CellValueBaseD2Ev[_ZN13CellValueBaseD5Ev]+0xd): undefined reference to `vtable for CellValueBase'
Cell.o: In function `CellValueBase::CellValueBase()':
Cell.cc:(.text._ZN13CellValueBaseC2Ev[_ZN13CellValueBaseC5Ev]+0x9): undefined reference to `vtable for CellValueBase'
Cell.o:(.rodata._ZTI9CellValueIfE[_ZTI9CellValueIfE]+0x10): undefined reference to `typeinfo for CellValueBase'
Column.o: In function `CellValueBase::CellValueBase()':
Column.cc:(.text+0x9): undefined reference to `vtable for CellValueBase'
sheet.o: In function `CellValueBase::CellValueBase()':
sheet.cc:(.text+0x9): undefined reference to `vtable for CellValueBase'
main.o: In function `CellValueBase::CellValueBase()':
main.cc:(.text+0x9): undefined reference to `vtable for CellValueBase'
collect2: error: ld returned 1 exit status
Makefile:8: recipe for target 'Spreadsheet' failed
make: *** [Spreadsheet] Error 1
And this is my code:
main.cc
#include <iostream>
#include "sheet.h"
using namespace std;
int main () {
Sheet *sht;
sht = new Sheet ();
return 0;
}//main
sheet.h
#ifndef SHEET_H
#define SHEET_H
#include "Column.h"
// Vaste grootte van de sheet
const int AantReg = 24;
const int AantKol = 80;
class Sheet
{
public:
Sheet ();
void getCell();
void begin();
void end();
private:
std::vector<Column*> sheetCol;//bevat de columns
int regels, kolommen;
};
#endif
sheet.cc
#include <iostream>
#include "sheet.h"
using namespace std;
Sheet::Sheet () {
regels = AantReg;
kolommen = AantKol;
cout << "Kolommen" << endl;
for (int i = 0; i < kolommen; i++) {
cout << "kolomnr: " << i << endl;
sheetCol.push_back(new Column(regels));
}
cout << endl << endl;
}
void Sheet::getCell () {
//TODO: fixen
}
void Sheet::begin () {
//TODO: deze shit ook fixen
}
void Sheet::end () {
}
Column.h
#include <vector>
#include "Cell.h"
class Column
{
public:
Column (int n);
//void getCell();
//void begin();
//void end();
private:
int aantCellen;
std::vector<Cell*> columnVec;//sla je de cellen in op
};
#endif
Column.cc
#include <iostream>
#include "Column.h"
using namespace std;
Column::Column(int n): aantCellen(n)
{
for (int i = 0; i < aantCellen; i++) {
cout << "celnr: " << i << endl;
columnVec.push_back(new Cell());
}
}//cell
Cell.h
#ifndef CELL_H
#define CELL_H
#include "CellValueBase.h"
#include <string>
#include <memory>
class Cell {
public:
Cell();
void setValueFloat(float newValue);
//void setValueInt(int newValue);
//void setValueString(std::string newValue);
//void setValueFormula(std::string newValue);
//std::unique_ptr<cellValueBase> readValue();
void emptyCell();
private:
std::unique_ptr<CellValueBase> value;
};
#endif
Cell.cc
#include "Cell.h"
#include <iostream>
using namespace std;
Cell::Cell() {
value.reset(nullptr);
cout << "hallo wereld ik ben een cel" << endl;
setValueFloat(3.14);
} // Cell
void Cell::setValueFloat(float newValue)
{
value = unique_ptr<CellValueBase>(new CellValue<float>(newValue));
value->returnValueNumber();
} // setValueFloat
CellValueBase.h
#ifndef CELLVALUEBASE_H
#define CELLVALUEBASE_H
#include <iostream>
#include <string>
#include <sstream>
#include <stdexcept>
class CellValueBase
{
public:
CellValueBase();
virtual ~CellValueBase() {};
//virtual std::string returnValueStringEdit() = 0;
virtual float returnValueNumber();
void emptyCell();
private:
};
CellValueBase::CellValueBase()
{
} // CellValueBase
template<typename T>
class CellValue final : public CellValueBase
{
public:
CellValue(T initial_value)
: CellValueBase(), value(initial_value)
{ }
~CellValue();
//std::string returnValueString();
//std::string returnValueStringEdit();
float returnValueNumber();
private:
T value;
};
template<typename T>
CellValue<T>::~CellValue()
{
// TODO
}
template<typename T>
float CellValue<T>::returnValueNumber() {
return value;
}
And the makefile:
CC = g++
CompileParms = -c -std=c++14 -Wall -Wextra
OBJS = Cell.o Column.o sheet.o main.o
Spreadsheet: $(OBJS)
$(CC) $(OBJS) -o spreadsheet
Cell.o: Cell.cc CellValueBase.h Cell.h
$(CC) $(CompileParms) Cell.cc
Column.o: Column.cc Column.h
$(CC) $(CompileParms) Column.cc
sheet.o: sheet.cc sheet.h
$(CC) $(CompileParms) sheet.cc
main.o: main.cc sheet.h
$(CC) $(CompileParms) main.cc
You have correctly understood that templates needs to be defined in their header file. But the class CellValueBase is not a template, so the definition of the CellValueBase constructor in the header file is incorrect. It means the constructor will be defined everywhere the header file is included.
The simple solution? Define the CellValueBase constructor inline in the class (like you already do with the destructor).
Furthermore, all virtual but non-abstract functions in a class must have a definition. So either make CellValueBase::returnValueNumber abstract or have an empty definition.
All in all, the CellValueBase class could look like this:
class CellValueBase
{
public:
CellValueBase() {} // <- Define inline
virtual ~CellValueBase() {};
//virtual std::string returnValueStringEdit() = 0;
virtual float returnValueNumber() = 0; // <- Declare abstract
void emptyCell();
private:
};
Look at CellValueBase.h. You can not define non-inline class methods outside of the class in header files. You must define them in .cpp files.
Move this method's definition to to CellValueBase.cpp:
CellValueBase::CellValueBase()
{
} // CellValueBase
Define non-inline methods or functions in header is totally bad practice. Error appears not at once, it appears only when you include this header in two cpp files. It means that linker founds two same methods definitions and that is the problem. If you would leave definition in your header CellValueBase.h and include CellValueBase.h once in .cpp file then there won't be any problems. But when you include CellValueBase.h more than once then linker founds duplicate definition.
But even if you know that you won't include header file with non-inline methods definitions more then once then you also should remember never to define non-inline functions or class methods outside classes. You can forget about your "1 include rule" for this file and later include it twice and linker will detect duplicate definition.
Also you can define template methods without specialization or define inline specialized template methods in header files.
I am currently working on a virtual run time environment program that is at a very early stage, i am prevented from continuing my work due to a linker error when using my makefile, provided below. The error i am receiving is:
g++ controller.o processor.o test.o -o final
controller.o: In function `Controller::run()':
controller.cpp:(.text+0x1e0): undefined reference to
Processor::codeParams(char)'
controller.o: In function `Controller::fetch()':
controller.cpp:(.text+0x290): undefined reference to `Controller::pc'
controller.cpp:(.text+0x299): undefined reference to `Controller::pc'
collect2: error: ld returned 1 exit status
makefile:16: recipe for target 'final' failed
make: *** [final] Error 1
I am unsure as to why i get this error as i thought i had defined these things in the source file corresponding to the header. All files will be given below so that the program can be compiled.
test.cpp:
#include <iostream>
#include <vector>
#include "includes/controller.h"
using namespace std;
int main()
{
vector<char> prog = {0x0};
Controller contr(prog);
cout << "Error Code: " << contr.run() << endl;
return 0;
}
controller.cpp:
/*
Author(s): James Dolan
File: controller.cpp
Build: 0.0.0
Header: includes/controller.h
DoLR: 21:39 11/1/2017
Todo: n/a
*/
#include "includes/controller.h"
Controller::Controller(vector<char> prog)
{
printf("Program:"); //Display program
for(auto i : program)
{
printf("%02X", i);
}
printf("\n");
Controller::program = program;
}
Controller::~Controller ()
{
}
int Controller::run()
{
bool runFlag = true;
int errorCode = 0;
char curCode;
vector<char> curInstr;
int paramRef;
while(runFlag)
{
curCode = fetch();
printf("curCode:%02X\n", curCode);
curInstr.push_back(curCode);
paramRef = proc.codeParams(curCode);
if (paramRef == 0xffff){runFlag = false; continue;} //Check if shutdown signal was returned, if so shutdown
printf("opcode good\n");
for(int i; i<paramRef; i++){curInstr.push_back(fetch());}
}
return errorCode;
}
char Controller::fetch()
{
return program[pc++]; //Return next instruction then increment the program counter
}
controller.h:
/*
Author(s): James Dolan
File: controller.h
Source: ../controller.cpp
DoLR: 21:39 11/1/2017
Todo: n/a
*/
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <iostream>
#include <vector>
#include <cstdlib>
#include "processor.h"
using namespace std;
class Controller{
public:
Controller(vector<char> prog);
~Controller();
int run();
protected:
private:
vector<char> program;
static int pc;
char fetch();
Processor proc();
};
#endif
processor.cpp:
#include "includes/processor.h"
Processor::Processor()
{
}
Processor::~Processor()
{
}
int codeParams(char code)
{
switch(code)
{
case 0x0: //Halt
return 0;
default:
printf("[ERROR!] Invalid opcode [%02X]", code);
return 0xffff; //Return shutdown signal
}
}
processor.h:
#ifndef PROCESSOR_H
#define PROCESSOR_H
#include <iostream>
#include <cstdlib>
class Processor{
public:
Processor();
~Processor();
int codeParams(char code);
protected:
private:
};
#endif
All if any help is appreciated massively as it will help me to continue with my passion of developing a fully fledged open-source virtual runtime enviroment like the java vm, thank you for your time.
In Controller.cpp you need a int Controller::pc; or int Controller::pc = 0;
In the header file you declared a static int named pc that exists somewhere. It needs to actually exist in a translation unit somewhere (in this case Controller.cpp) so that when the linker tries to find it... it exists.
In Processor.cpp your signature should look like int Processor::codeParams(char code) to let the compiler know that is Processor's codeParams and not a random function named codeParams that happens to also take a character.
For the member function Processor::codeParams you should define it as:
int Processor::codeParams(char code)
// ~~~~~~~~~~~
{
...
}
Otherwise it's just a normal (non–member) function.
For the static member Controller::pc you should define it outside of the class definition, in controller.cpp.
// Controller.h
class Controller {
...
private:
static int pc;
};
// controller.cpp
int Controller::pc;
I have a very simple setup to try to test a staticLibrary:
I get error Syntax error: Identifier MyDataT, which points me to the function declaration in MyLib.h? Any reason why struct isn't recognized in the second solution?
Here is my pseudo code:
//MSGDefs.h ==> header file only contains struct defs like this:
typedef struct __msg {
unsigned long dest;
unsigned long src;
}MsgT
typedef struct __mydata : public MsgT
{
TimeT time;
DateT date;
}MyDataT;
//======== Library generates staic lib MyLib.lib, this generates library fine=======
//MyLib.h
#include MSGdefs.h
class X{
void process(MyDataT *data);
}
//MyLib.cpp
void X::process(MyDataT *data) { // do processing here ...}
//========================================
//MyTestLibProj.cpp -- Another Solution links to MyLib.lib
#include MyLib.h ==> This causes error of identifier MyDataT ???
int main(){
// X x = new X();
}
I've got 2 classes, casilla.cpp and casilla.h.
In the cpp one I get the error of class redefined, and in .h "there's a previous definition of the classs casilla. I've searched for it in the internet, but not even putting casilla:: before one or putting the headers work. Here's the code:
Casilla.h:
#ifndef CASILLA_H_
#define CASILLA_H_
using namespace std;
class Casilla { //previous definition of ‘class Casilla’
public:
casilla(); //ISO C++ forbids declaration of ‘casilla’ with no type [-fpermissive]
virtual ~casilla(); //expected class-name before ‘(’ token
void SetNumeroCasilla (int _numero);
};
/* namespace std */
#endif /* CASILLA_H_ */
Casilla.cpp:
#include "Casilla.h"
#include "Tablero.h"
using namespace std;
#include <iostream>
#include <iomanip>
class Casilla //errors :Multiple markers at this line
- redefinition of ‘class Casilla’
- Line breakpoint: Casilla.cpp [line:
17]
{
int fila;
int columna;
int numero;
public:
// default constructor
Casilla::Casilla()
: fila(-1)
, columna(-1)
, numero(0)
{ }
int GetNumero() {return numero;}
void SetCasillaPosition (int _fila, int _columna) //set a cell position
{
fila = _fila;
columna = _columna;
}
void SetNumeroCasilla (int _numero) //set a cell value
{
numero = _numero;
}
void SetCasillaFull (int _fila, int _columna, int _numero) //set a cell position and value
{
fila = _fila;
columna = _columna;
numero = _numero;
}
};
Just changed the code with new errors shown. The redefined error persists, what did I do wrong?
In casilla.cpp, you're redefining casilla... class casilla { .. }; is a class definition, and you have it twice: once in your header and once in your cpp. Hence, the redefinition error.
All you need to do in the .cpp is provide definitions for the class methods you declared in your .h:
#include "Casilla.h"
// other includes
// define the default constructor:
casilla::casilla()
: fila(-1)
, columna(-1)
, numero(0)
{ }
// define this function
void casilla::SetNumeroCasilla (int _numero)
{
// something
}
I'm using the Arduino IDE 1.0.5-r2 and trying to create a class with two member variables, _pinA and _pinB. When I call the constructor from my Arduino sketch, I get this error:
RotaryEncoderReader.cpp:6: error: request for member '_pinB' in 'this', which is of non-class type 'RotaryEncoderReader* const'
The constructor can be called from a regular C++ files compiled using GCC, and there are no errors. Am I missing something about how to use a class constructor with an Arduino?
Here is the class header:
#ifndef RotaryEncoderReader_h
#define RotaryEncoderReader_h
#include "Arduino.h"
class RotaryEncoderReader {
private:
int _pinA;
int _pinB;
volatile long encoderPos;
public:
RotaryEncoderReader( int newPinA, int newPinB );
void doEncoderA();
void doEncoderB();
long getPosition();
};
#endif
Here's the implementation:
#include "RotaryEncoderReader.h"
RotaryEncoderReader::RotaryEncoderReader( int newPinA, int newPinB )
: _pinA(newPinA),
_pinB(newPinB),
encoderPos(0)
{
}
void RotaryEncoderReader::doEncoderA()
{
//Irrelevant
}
void RotaryEncoderReader::doEncoderB()
{
//Irrelevant
}
long RotaryEncoderReader::getPosition()
{
return _pinA + _pinB;
}
And here's the Arduino sketch:
#include <RotaryEncoderReader.h>
int pinA = 2;
int pinB = 3;
RotaryEncoderReader reader(pinA, pinB);
void setup()
{
}
void loop()
{
}