I am getting the error shown below while linking the code. How can I fix this problem?
It seems the static variable is not getting initialized.
#include <iostream>
#include <cstdlib>
using namespace std;
struct name{
char c;
};
class List {
static name *a;
public:
static void modify()
{
a = new name();
cout<<"yes";
}
};
name List::*a = NULL;
int main()
{
List::modify();
}
g++ O3 -Wall -c -fmessage-length=0 -o sample.o "..\\sample.cpp"
g++ -o sample.exe sample.o
sample.o:sample.cpp:(.text.startup+0x35): undefined reference to `List::a'
collect2.exe: error: ld returned 1 exit status
name List::*a = NULL; doesn't do what you expected. It defines a global variable named a, which is a pointer to non-static member of List of type name.
The definition of List::a should be
name* List::a = NULL;
Related
Here's a simple set of files that reproduce the problem I'm having:
c.h:
void dummy();
c.cpp:
#include <stdio.h>
extern "C" {
#include "c.h"
}
class Bubu {
public:
static Bubu *getInstance() {
if (_instance == NULL) {
_instance = new Bubu;
}
return _instance;
}
private:
static Bubu *_instance;
};
Bubu *_instance = NULL;
void dummy() {
printf("bubu called\n");
Bubu *ptr = Bubu::getInstance();
}
main.cpp:
extern "C" {
#include "c.h"
}
int main() {
dummy();
return 0;
}
When I compile I get this:
g++ -W -Wall -c c.cpp -o c.o
c.cpp: In function ‘int bubu()’:
c.cpp:24: warning: unused variable ‘ptr’
g++ -W -Wall main.cpp c.o -o main
c.o: In function `Bubu::getInstance()':
c.cpp:(.text._ZN4Bubu11getInstanceEv[Bubu::getInstance()]+0x7): undefined reference to `Bubu::_instance'
c.cpp:(.text._ZN4Bubu11getInstanceEv[Bubu::getInstance()]+0x1d): undefined reference to `Bubu::_instance'
c.cpp:(.text._ZN4Bubu11getInstanceEv[Bubu::getInstance()]+0x24): undefined reference to `Bubu::_instance'
collect2: ld returned 1 exit status
make: *** [main] Error 1
Compilation exited abnormally with code 2 at Tue Dec 15 09:15:21
I've seen the answer to other similar questions but there the problem is either a missing Bubu:: when calling the static method or lack of initialisation of the static member outside the class declaration or missing the extern "C" construct. I'm fairly certain that I'm not making those mistakes ... I'm definitely making other(s).
Can you please explain what's going on?
When you define a static variable inside a class, you have to define it outside the class also. You tried to do this, but
Bubu *_instance = NULL;
will just make a global pointer to Bubu, not instantiate the static one inside the class. You need to use
Bubu *Bubu::_instance = NULL;
to tell the compiler this will be the static variable inside the class.
Have the following program:
#include <iostream>
#include <string>
using namespace std;
class Record
{
public:
static Record* GetInstance(string name);
void printName();
private:
Record(string name);
string name_;
static Record *record;
};
Record::Record(string name)
:name_(name)
{
}
Record*
Record::GetInstance(string name)
{
if(record == NULL) {
record = new Record(name);
}
return record;
}
void
Record::printName()
{
cout << name_ << endl;
}
int main()
{
Record* record1 = Record::GetInstance("sellers");
record1->printName();
Record* record2 = Record::GetInstance("customers");
record2->printName();
}
I am compiling and linking with:
g++ -g -c -Wall main.cpp
g++ -g -Wall main.o -o main
The compilation completes without error(1st command). But the linking is giving this error:
Undefined first referenced
symbol in file
Record::record main.o
ld: fatal: Symbol referencing errors. No output written to main
collect2: ld returned 1 exit status
Wondering how to correct this.
You need to define the variable somewhere, i.e.
Record *Record::record;
This is the error I am keep getting . undefined reference to my class. I am not sure. I think I m linking them. this is how my main looks like.
#include <iostream>
#include "randomNumberMagnifier.h"
using namespace std;
int main()
{
randomNumberMagnifier r1, r2;
cout << "Random Number "<< r1.getRandomNumber();
cout << endl;
}
I am not sure what I am doing wrong.
this is what it looks like. when I compile
[singha1#cs1 p4]$ g++ -c randomNumberMagnifier.cpp
[singha1#cs1 p4]$ g++ -o p4Driver.cpp
g++: no input files
p4Driver.cpp:(.text+0x8c): undefined reference to `randomNumberMagnifier::getRandomNumber
collect2: ld returned 1 exit status
#ifndef RANDOMNUMBERMAGNIFIER_H
#define RANDOMNUMBERMAGNIFIER_H
class randomNumberMagnifier
{
int addFactor;
int multFactor;
bool addOn;
bool multOn;
int randomNumber;
static const int MAX_ADD_FACTOR = 100;
static const int MAX_MULT_FACTOR = 20;
static const int MAX_RANDOM = 200;
public:
randomNumberMagnifier();
//~randomNumberMagnifer();
randomNumberMagnifier& operator=(const randomNumberMagnifier& rhs);
randomNumberMagnifier(const randomNumberMagnifier& arandom);
randomNumberMagnifier(bool aState, bool mState);
int randomMagnifier();
int getAdd();
int getMult();
bool getAddState();
bool getMultState();
int getRandomNumber();
};
#endif
g++ -o p4Driver.cpp
That doesn't say what it's supposed to compile to, which is what -o is supposed to be for. You want:
g++ -c randomNumberMagnifier.cpp
g++ -c p4Driver.cpp
g++ randomNumberMagnifier.o p4Driver.o -o p4Driver
Or just:
g++ randomNumberMangifier.cpp p4Driver.cpp -o p4Driver
you need to provide randomNumberMagnifier.o to g++ command, so it can find function definition. I tested with below command and i worked
g++ -o p4Driver p4Driver.cpp randomNumberMagnifier.o
Looked around and found a few similar questions but none of them were the same. Most had to do with the constructor or destructor. This issue is, more than likely, a result of my rusty C++ linker memory (picking it back up after a few years).
I'll keep it real simple since this is probably a basic misunderstanding of the linker:
data.h
#pragma once
namespace test {
class Data_V1 {
public:
// some getters/setters
int getData() { return _d; }
void setData( int d ) { _d = d; }
private:
// some data
int _d;
};
}
builder.h
#pragma once
namespace test {
template <class V>
class Builder {
public:
void build();
};
}
builder.cpp
#include <iostream>
#include "builder.h"
namespace test {
template<class V>
void Builder<V>::build() {
std::cout << "Insert building logic" << std::endl;
}
}
main.cpp
#include "builder.h"
#include "data.h"
using namespace test;
int main(int argc, char* argv[]) {
Builder<Data_V1> b;
b.build();
}
compiling:
g++ -Wall -ansi -pedantic -c builder.cpp
g++ -Wall -ansi -pedantic -c main.cpp
g++ -Wall -ansi -pedantic -o main main.o builder.o
Link error:
Undefined symbols for architecture x86_64:
"test::Builder<test::Data_V1>::build()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Any help would be appreciated!
Template definitions need to be visible to all translation units. Move the definition from the cpp to the header.
Builder.h
#pragma once
namespace test {
template <class V>
class Builder {
public:
void build();
};
template<class V>
void Builder<V>::build() {
std::cout << "Insert building logic" << std::endl;
}
}
Before you ask, no, there's no way to hide the implementation unless you know all possible specializations beforehand.
Templates represent a generalized form for the creation of a new class. If the implementation is not visible, when you attempt to specialize the template, the compiler can't know what code to generate.
please consider these files:
p.h:
#ifndef _p_h_
#define _p_h_
class p{
public:
static void set_func(int(*)());
private:
static int (*sf)();
};
#endif
p.cpp:
#include "p.h"
#include <cstdio>
int (p::*sf)() = NULL; //defining the function pointer
void p::set_func(int(*f)()){
sf = f;
}
main.cpp:
#include "p.h"
#include <iostream>
int function_x(){
std::cout << "I'm function_x()" << std::endl;
return 1234;
}
int main(){
p::set_func(function_x);
}
when compiling, I get this:
$ g++ -o pp main.cpp p.cpp
/tmp/ccIs0M7r.o:p.cpp:(.text+0x7): undefined reference to `p::sf'
collect2: ld returned 1 exit status
but:
$ g++ -c -o pp p.cpp
compiles right.
What's wrong with the code? I just can't find where the problem is, please your help will be more than appreciated.
Thanks.
Your attempt at defining p::sf is incorrect – yours is a definition of a global variable named sf that is of type int (p::*)(), i.e. a pointer to a member function. Consequently p::sf remains undefined, hence the linker error.
Try this instead:
int (*p::sf)() = 0;
// or,
typedef int (*p_sf_t)();
p_sf_t p::sf = 0;
The difference is because error only occurs when you actually link the program. The problem is in your declaration of the static function pointer. The correct syntax is:
int (*p::sf)() = NULL; //defining the function pointer
You define a member function pointer and not a function pointer. I'm not sure what the correct syntax is, but I would have tried something like this:
int (*p::sf)() = NULL;
I will not give another answer (ildjarn answer is correct) but i will suggest you another way of achieving the same without static initialization (and the burdens it implies)
class p{
public:
typedef int (*func_t)();
static void set_func(func_t v) {
func_t& f = getFuncRef();
f = v;
}
static void call_func() {
func_t& f = getFuncRef();
assert( f != 0);
f();
}
private:
static func_t& getFuncRef() {
static func_t sf = 0;
return sf;
}
};
in this way you delegate the static initialization to a static function variable, which doesn't have the initialization order problems that affect static data variables, and is lazy-initialised