pointer to function methods within the class not working - c++

I'm trying to to write a code that will call a function that receive a pointer to other function within the same class, and call get_num method from main.
but when doing include to TestClass.h from main, I'm getting linkage errors
class TestClass{
public:
void get_num(int num);
void foo(int num, void(TestClass::*function)(int));
void boo(int num);
};
void TestClass::boo(int num)
{
std::cout << "number: " << num << std::endl;
}
void TestClass::foo(int num, void(TestClass::*function)(int))
{
(this->*function)(num);
}
void TestClass::get_num(int num)
{
foo(num, &TestClass::boo);
}
Following is the main code:
#include "TestClass.h"
int main()
{
TestClass tc1;
tc1.get_num(5);
system("pause");
return 1;
}
The following errors appears:
1>main.cpp
1>TestClass.obj : error LNK2005: "public: void __thiscall TestClass::boo(int)" (?boo#TestClass##QAEXH#Z) already defined in main.obj
1>TestClass.obj : error LNK2005: "public: void __thiscall TestClass::foo(int,void (__thiscall TestClass::*)(int))" (?foo#TestClass##QAEXHP81#AEXH#Z#Z) already defined in main.obj
1>TestClass.obj : error LNK2005: "public: void __thiscall TestClass::get_num(int)" (?get_num#TestClass##QAEXH#Z) already defined in main.obj
1>c:\Proj4.exe : fatal error LNK1169: one or more multiply defined symbols found

Pointer to a method is not the same as a pointer to a simple function. If you only want to be able to accept a pointer to the method of the same class you can rewrite your method like this:
void TestClass::foo(int num, void(TestClass::*function)(int))
{
(this->*function)(num);
}
void TestClass::get_num(int num)
{
foo(num, &TestClass::boo);
}
This allows foo() to accept a pointer to any method in TestClass but not to any method of any other class nor to a simple function. It also calls the received method on the same object (note: this in this->*function).

Related

Linker can't find a namespace's functions

See code below. There's something wrong with it, because the linker is complaining it can't find the Memory's functions, but I can't figure out why.
memory.h
#pragma once
#include "includes.h" //it just includes other strandard headers.
class MemoryUnit
{
public:
MemoryUnit() {}
virtual int getValue() = 0;
virtual int getSize() = 0;
virtual void setValue(int) = 0;
virtual ~MemoryUnit() {};
};
class Byte : public MemoryUnit
{
int value;
public:
static int size;
Byte(int byte) :value(byte) {};
int getSize() { return size; }
int getValue() { return value; };
void setValue(int byte) { value = byte; }
~Byte() {};
};
namespace Memory
{
extern int size;
extern MemoryUnit** map;
void checkAddress(int address);
int read(int adress);
MemoryUnit* getOperation(int address);
void write(int adress, MemoryUnit* data);
void writeByte(int adress, int data);
}
memory.cpp
#include "includes.h"
#include "memory.h"
#include "simulator.h" // it contains only externed constants.
namespace Memory
{
int size = 0;
MemoryUnit** map = NULL;
inline MemoryUnit* getOperation(int address)
{
return map[address];
}
inline void checkAddress(int address)
{
if (address < 0 || address >= MAX_MEMORY_SIZE)
throw std::out_of_range("Invalid memory address.");
}
inline int read(int address)
{
checkAddress(address);
return map[address]->getValue();
}
inline void write(int address, MemoryUnit* data)
{
checkAddress(address);
delete map[address];
map[address] = data;
}
inline void writeByte(int address, int data)
{
checkAddress(address);
map[address]->setValue(data);
}
}
Everywhere the class/namespace memory.h declares is includes memory.h. Is here anything wrong in the code below?
Edit:
I'm using Visual Studio 2015.
Errors I got when building the project:
LNK1120 5 unresolved externals simulator.exe
LNK2019 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" referenced in function "void __cdecl ALU::setFlags(int)" alu.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" cu.obj
LNK2019 unresolved external symbol "class MemoryUnit * __cdecl Memory::getOperation(int)" referenced in function "void __cdecl CU::run(void)" cu.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" helpers.obj
LNK2019 unresolved external symbol "void __cdecl Memory::write(int,class MemoryUnit *)" referenced in function "void __cdecl readProgramCommands(void)" helpers.obj
LNK2001 unresolved external symbol "public: virtual int __thiscall MemoryPointer::getValue(void)" helpers.obj
LNK2001 unresolved external symbol "public: virtual int __thiscall IndirectMemoryPointer::getAddress(void)" helpers.obj
LNK2001 unresolved external symbol "void __cdecl Memory::writeByte(int,int)" main.obj
alu.h and alu.cpp for the first error:
//alu.h
#pragma once
#include "includes.h"
#include "operation.h"
namespace ALU
{
int operation(Operation* op);
void setFlags(int result);
}
//alu.cpp
#include "includes.h"
#include "simulator.h"
#include "alu.h"
#include "memory.h"
#include "operation.h"
namespace ALU
{
int operation(Operation* operation)
{
// ...
setFlags(result);
return result;
}
inline void setFlags(int result)
{
Memory::writeByte(FLAG_Z, result == 0);
// ...
}
}
You need to put the inline function definition inside your header file (they both must appear in every translation unit where they are used), you can separate declaration and definition but both must be in the header file. Also they must be declared as inline.
N4140 dcl.fct.spec 7.1.2.4
An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly
the same definition in every case (3.2). [ Note: A call to the inline function may be encountered before its
definition appears in the translation unit. —end note ] If the definition of a function appears in a translation
unit before its first declaration as inline, the program is ill-formed.
When you're using inline functions or methods, their definitions should be visible for every source unit that uses them. You defined your inline functions in Memory.cpp, that's why you get 'unresolved' linker error.
To fix your problem you can:
Remove inline modifier and keep functions definitions in Memory.cpp.
Keep inline modifier but move functions definitions to Memory.h.

C++ LNK 2019 Error with templates/classes

So this part of the code is a small part of a large project. I can't copy the entire project but it's really just 2 lines making the error. I'm trying to access the function "mergeSort" from the class Metrics. Metrics is a different class than the one I'm trying to access it in. I've defined mergeSort and also #included Metrics in the class I'm working with. I've also defined the constructor. Here is the piece of code:
void Document::createHashWords()
{
Node* heads[97];
string* allWords = parseWords();
int numWords = getdWordCt();
for ( int i = 0; i < numWords; i++ )
{
char* word = (char*)allWords[i].c_str();
int k = hashWord(word,97);
insertWord(heads,k,allWords[i]);
}
for ( int i = 0; i < 97; i++ )
{
Node* temp = heads[i];
int size = 0;
while (temp != NULL)
{
size++;
temp = temp->getNext();
}
int* countArr = new int[size];
temp = heads[i];
for ( int i = 0; i < size; i++ )
{
countArr[i] = temp->getCount();
temp = temp->getNext();
}
Metrics <int> toSort;
toSort.mergeSort(countArr,size);
}
}
the Code that is causing the problem is the last 2: Metrics toSort and toSort.mergeSort(countArr,size);.
Here is the Metrics class:
template <class T>
class Metrics
{
private:
int id;
public:
Metrics();
~Metrics();
void selectionSort(T *arr, int n);
void insertionSort(T *arr, int n);
void merge(T *a, int numA, T *b, int numB, T *c);
void mergeSort(T *arr, int n);
};
I've defined mergeSort in the .cpp file for that class.
Here is my build error:
1>Document.obj : error LNK2019: unresolved external symbol "public: __thiscall Metrics<int>::Metrics<int>(void)" (??0?$Metrics#H##QAE#XZ) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords#Document##QAEXXZ)
1>Document.obj : error LNK2019: unresolved external symbol "public: __thiscall Metrics<int>::~Metrics<int>(void)" (??1?$Metrics#H##QAE#XZ) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords#Document##QAEXXZ)
1>Document.obj : error LNK2019: unresolved external symbol "public: void __thiscall Metrics<int>::mergeSort(int *,int)" (?mergeSort#?$Metrics#H##QAEXPAHH#Z) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords#Document##QAEXXZ)
1>C:\Users\Kevin\Documents\Visual Studio 2012\Projects\CMPSC 122 Checkpoint 2\Debug\CMPSC 122 Checkpoint 1.exe : fatal error LNK1120: 3 unresolved externals
If I remove those 2 lines, I can compile fine. I just don't know why those 2 lines are wrong. I need to access that function from the Metrics class.
template <class T>
class Metrics
{
private:
int id;
public:
Metrics<T>() {}
~Metrics<T>() {}
void selectionSort(T *arr, int n);
void insertionSort(T *arr, int n);
void merge(T *a, int numA, T *b, int numB, T *c);
void mergeSort(T *arr, int n);
};
So this is now my Metrics class:
template <class T>
class Metrics
{
private:
int id;
public:
Metrics() {}
~Metrics() {}
void selectionSort(T *arr, int n);
void insertionSort(T *arr, int n);
void merge(T *a, int numA, T *b, int numB, T *c);
void mergeSort(T *arr, int n);
};
I commented out the definitions of the constructor/destructor in the Metrics.cpp file like so:
//template <class T>
//Metrics<T>::Metrics()
//{
//}
//template <class T>
//Metrics<T>::~Metrics()
//{
//}
And now this is my error code:
1>Document.obj : error LNK2019: unresolved external symbol "public: void __thiscall Metrics::mergeSort(int *,int)" (?mergeSort#?$Metrics#H##QAEXPAHH#Z) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords#Document##QAEXXZ)
1>C:\Users\Kevin\Documents\Visual Studio 2012\Projects\CMPSC 122 Checkpoint 2\Debug\CMPSC 122 Checkpoint 1.exe : fatal error LNK1120: 1 unresolved externals
The missing symbol seems to be the default ctor for Metrics, the one that takes no arguments. Have you defined it? You need to get it included somehow in the same translation unit. The usual way would be to define it in the header file:
template <typename T>
Metrics<T>::Metrics() {}
Template functions need to be defined in every translation unit (.cpp) they're used in, so you want all of Metrics' member functions to be defined in Metrics.h, as if they were all inlined.
They work differently from normal functions because the code generated is different for every different type used for T, so the compiler can't know what versions to generate when compiling Metrics.cpp.

Default Arguments defining static member

I m reading The C++ Programming Language 4e. In the part of Default Argument I dont understand below code. I try to compile but there is an error. Anyway what Bjarne trying to explaing? A default argument is type checked at the time of the function declaration and evaluated at the
time of the call. For example:
class X
{
public:
static int def_arg;
void f(int = def_arg);
// ...
};
int X::def_arg = 7;
void g(X& a)
{
a.f(); // maybe f(7)
a.def_arg = 9;
a.f(); // f(9)
}
Error is :
unresolved external symbol "public: void __thiscall X::f(int)" (?f#X##QAEXH#Z) referenced in function "void __cdecl g(class X &)" (?g##YAXAAVX###Z)
MS c++ 2013
You just declared f but need to define the body of f:
void f(int = def_arg);
For example
void X::f(int)
{
// Do something
}
or
class X
{
// ...
void f(int = def_arg)
{
// Do something
}
};
Live code.

Templated class linking error when used to declare object in other class

I created a templated data class (CAnyData, please see its header file copy for your reference), with which I declared some variables in my another class (CConstantDataBlock, please see its header file copy for your reference). As you may see, the latter one is nearly an empty class. But when I compiled my project, the VS2008 compiler thowed the following linking errors. Would please help me figure out what's wrong with my CConstantDataBlock and/or CAnyData?
1>------ Build started: Project: Tips, Configuration: Debug Win32 ------
1>Compiling...
1>ConstantDataBlock.cpp
1>Linking...
1> Creating library F:\Tips\Debug\Tips.lib and object F:\Tips\Debug\Tips.exp
1>ConstantDataBlock.obj : error LNK2019: unresolved external symbol "public: __thiscall CAnyData<double>::~CAnyData<double>(void)" (??1?$CAnyData#N##QAE#XZ) referenced in function __unwindfunclet$??0CConstantDataBlock##QAE#XZ$0
1>ConstantDataBlock.obj : error LNK2019: unresolved external symbol "public: __thiscall CAnyData<int>::~CAnyData<int>(void)" (??1?$CAnyData#H##QAE#XZ) referenced in function __unwindfunclet$??0CConstantDataBlock##QAE#XZ$0
1>ConstantDataBlock.obj : error LNK2019: unresolved external symbol "public: __thiscall CAnyData<double>::CAnyData<double>(void)" (??0?$CAnyData#N##QAE#XZ) referenced in function "public: __thiscall CConstantDataBlock::CConstantDataBlock(void)" (??0CConstantDataBlock##QAE#XZ)
1>ConstantDataBlock.obj : error LNK2019: unresolved external symbol "public: __thiscall CAnyData<int>::CAnyData<int>(void)" (??0?$CAnyData#H##QAE#XZ) referenced in function "public: __thiscall CConstantDataBlock::CConstantDataBlock(void)" (??0CConstantDataBlock##QAE#XZ)
1>F:\Tips\Debug\Tips.exe : fatal error LNK1120: 4 unresolved externals
1>Build log was saved at "file://f:\Tips\Tips\Debug\BuildLog.htm"
1>Tips - 5 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
#pragma once
#include <string>
using namespace std;
template <class T>
class CAnyData
{
public:
CAnyData(void);
CAnyData(int nWordNumber, string sContents, T Type, int nWidth, int nPrecision);
~CAnyData(void);
// Operators
CAnyData( const CAnyData& rhs );
const CAnyData& operator = (const CAnyData& rhs);
// Must define less than relative to name objects.
bool operator<( const CAnyData& AnyData ) const;
// Compares profile's of two objects which represent CAnyData
inline bool operator ==(const CAnyData& rhs) const;
// Get properties
inline int WordNumber() const { return m_nWordNumber; }
inline const string& Contents() const { return m_sContents; }
inline const T& DataType() const { return m_Type; }
inline int Width() const { return m_nWidth; }
inline int Precision() const { return m_nPrecision; }
// Set properties
void WordNumber(int nWordNumber) const { m_nWordNumber = nWordNumber; }
void Contents(string sContents) const { m_sContents = sContents; }
void DataType(T Type) const { m_Type = Type; }
void Width(int nWidth) const { m_nWidth = nWidth; }
void Precision(int nPrecision) const { m_nPrecision = nPrecision; }
protected:
void Init(void);
protected:
int m_nWordNumber;
string m_sContents;
T m_Type;
int m_nWidth;
int m_nPrecision;
};
#pragma once
#include "AnyData.h"
// Constants block
// This block consists of 64 words to be filled with useful constants.
class CConstantDataBlock
{
public:
CConstantDataBlock(void);
~CConstantDataBlock(void);
protected:
CAnyData<int> m_nEarthEquatorialRadius;
CAnyData<int> m_nNominalSatelliteHeight;
CAnyData<double> m_dEarthCircumference;
CAnyData<double> m_dEarthInverseFlattening;
};
It seems that you do not have definitions for several of the methods of CAnyData, including the default constructor and the destructor. When you use these in your CConstantDataBlock-class, the constructor and destructor are required though.
Since CAnyData is a class-template, all definitions should be written directly into the header-file (just as you have done with all the getters and setters).

C++ LNK2019 ( between project classes )

I have an very strange error: when I want to use the SocialServer::Client class from my SocialServer::Server class, the linker threw me two LNK2019 errors :
Error 1 error LNK2019: unresolved external symbol "public: void __thiscall SocialServer::Client::Handle(void)" (?Handle#Client#SocialServer##QAEXXZ) referenced in function "private: static unsigned int __stdcall SocialServer::Server::listenThread(void *)" (?listenThread#Server#SocialServer##CGIPAX#Z) C:\Users\benjamin\Documents\Visual Studio 2010\Projects\FCX Social Server\SocialServer Core\Server.obj SocialServer Core
Error 2 error LNK2019: unresolved external symbol "public: __thiscall SocialServer::Client::Client(unsigned int)" (??0Client#SocialServer##QAE#I#Z) referenced in function "private: static unsigned int __stdcall SocialServer::Server::listenThread(void *)" (?listenThread#Server#SocialServer##CGIPAX#Z) C:\Users\benjamin\Documents\Visual Studio 2010\Projects\FCX Social Server\SocialServer Core\Server.obj SocialServer Core
However , these 2 missing function are correctly implemented :
Client.h
#pragma once
#include "dll.h"
namespace SocialServer
{
class __social_class Client
{
public:
Client(SOCKET sock);
~Client();
void Handle();
private:
static unsigned __stdcall clientThread(void* value);
SOCKET _socket;
uintptr_t _thread;
unsigned int _thread_id;
};
}
Client.cpp
#pragma once
#include "Client.h"
namespace SocialServer
{
Client::Client(SOCKET socket)
{
this->_socket = socket;
}
Client::~Client()
{
}
void Client::Handle()
{
std::cout << " New client " << std::endl;
this->_thread = _beginthreadex(NULL, 0, Client::clientThread, &this->_socket, CREATE_SUSPENDED, &this->_thread_id);
ResumeThread((HANDLE)this->_thread);
}
unsigned __stdcall Client::clientThread(void* value)
{
// Some code to execute here ...
}
}
Where does the problem comes from ?
i've found the solution.
In a function that's used by _beginthreadex() (with unsigned __stdcall) , always add a return at the end.