So i had the following code which ran perfectly.
Here "rngSource" makes an instance of the class contained in rand.h. rng.rFloat64() calls random numbers between 0 and 1.
main.cpp
#include "rand.h" // rngSource
rngSource rng;
class particle{
public:
double r[nd], v[nd];
particle()
{
for (int i=0; i<nd; ++i)
{
r[i]=L*rng.rFloat64();
v[i]=rng.rFloat64();
}
}
};
But when I tried to separate the class implementation from main.cpp into particle.h and particle.cpp, as indicated below:
particle.h
#ifndef particle_H
#define particle_H
class particle{
public:
double r[2], v[2];
particle();
};
#endif
particle.cpp
#include "rand.h" // rngSource
#include "particle.h"
particle::particle()
{
double ran = (double) rand()/(double)RAND_MAX;
static const double L=10;
for (int i=0; i<2; ++i)
{
r[i]=L*ran;
v[i]=ran;
}
}
While the new main.cpp looks like this:
#include "rand.h" /* rngSource() */
#include "particle.h" /* particle class */
rngSource rng;
int main(){
rng.rseed(getpid()*time(NULL));
particle p[N];
....
}
But when i try to compile i get the following errors:
particle.cpp: In constructor ‘particle::particle()’:
particle.cpp:20:17: error: ‘rng’ was not declared in this scope
r[i]=L*rng.rFloat64(); //ran;
^
particle.o:(.data+0x0): multiple definition of `rng_cooked'
new.o:(.data+0x0): first defined here
particle.o:(.data+0x1300): multiple definition of `kn'
new.o:(.data+0x1300): first defined here
particle.o:(.data+0x1500): multiple definition of `wn'
new.o:(.data+0x1500): first defined here
particle.o:(.data+0x1700): multiple definition of `fn'
new.o:(.data+0x1700): first defined here
new.cpp:(.text+0x1fb1): undefined reference to `rngSource::rseed(long long)'
particle.o: In function `particle::particle()':
particle.cpp:(.text+0x1fa2): undefined reference to `rngSource::rseed(long long)'
particle.cpp:(.text+0x1fb5): undefined reference to `rngSource::rFloat64()'
particle.cpp:(.text+0x1fda): undefined reference to `rngSource::rFloat64()'
collect2: error: ld returned 1 exit status
Would anyone here happen to know how to fix this?
thank you.
Three problems.
Problem 1:
particle.cpp: In constructor ‘particle::particle()’:
particle.cpp:20:17: error: ‘rng’ was not declared in this scope
r[i]=L*rng.rFloat64(); //ran;
The ultra cheesy answer is to add extern rngSource rng; to particle.cpp above the particle constructor. extern means this variable exists, but its storage is allocated elsewhere. The linker will track it down for you. This is quick, dirty, and will get you back on the road with minimal code changes.
Better solutions are to add extern rngSource rng; to rand.h and then define rngSource rng; in rand.cpp for all users or placing extern rngSource rng; in a brand new main.h and include main.h in particle and other modules called by main.
The best solution is probably to create a bool init(rngSource & rng) function in particle and do grunt work the constructor's currently doing. That way if rng doesn't exist, the compiler catches it when you try to call init.
particle p[N];
for (size_t index; index < N; index++)
{
p[index].init(rng);
}
Problem 2
particle.o:(.data+0x0): multiple definition of `rng_cooked'
new.o:(.data+0x0): first defined here
particle.o:(.data+0x1300): multiple definition of `kn'
new.o:(.data+0x1300): first defined here
particle.o:(.data+0x1500): multiple definition of `wn'
new.o:(.data+0x1500): first defined here
particle.o:(.data+0x1700): multiple definition of `fn'
new.o:(.data+0x1700): first defined here
rng_cooked, kn, wn, and fn are almost certainly being defined in rand.h. This means everyone who includes rand.h tries to create their own version of those variables resulting in collisions when the linker tries to line up names with storage locations.
Solution is similar to the first problem: Add extern to the variable definitions in the rand.h and define them in rand.cpp.
Problem 3
new.cpp:(.text+0x1fb1): undefined reference to `rngSource::rseed(long long)'
particle.o: In function `particle::particle()':
particle.cpp:(.text+0x1fa2): undefined reference to `rngSource::rseed(long long)'
particle.cpp:(.text+0x1fb5): undefined reference to `rngSource::rFloat64()'
particle.cpp:(.text+0x1fda): undefined reference to `rngSource::rFloat64()'
No idea. Are you certain you are passing rand.cpp to gcc?
Related
Related to this. I'd like to avoid using global variables so I resorted to using structs with enum and std::string[] (see link) in order to build menus for a small application. I would also like to have these enums in a separate header file. The selected answer in the link implies using --std=c++17, which I'd like to avoid, at least for now, and decided to use a static const std::string[] -- no need to include extra array or vector since this is initialized once, never modified, only called, ALL is always known.
As other answers on this have made it clear, I need to either initialize A::names outside the struct, or use a static const std::string& setter (see this, for example). But all the answers so far dealt with a std::string, not an array, std::string[].
This is a simple example of what I tried. It simply tries to print the contents of A::names using a for() loop iterating through the enum in struct A:
a.h:
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
#include <string>
struct A
{
enum E { ONE, TWO, ALL };
static const std::string names[ALL];
};
#endif // A_H_INCLUDED
a.cpp:
#include "a.h"
static const std::string A::names[A::ALL] { "one", "two" };
main.cpp:
#include "a.h"
#include <iostream>
int main()
{
for(int i=A::ONE; i<A::ALL; ++i)
std::cout << A::names[i] << '\n';
return 0;
}
The error after g++ main.cpp is:
main.cpp:(.text+0x24): undefined reference to `A::names[abi:cxx11]'
collect2: error: ld returned 1 exit status
Seeing the cxx11, I thought g++ --std=c++11 main.cpp would solve it, but it doesn't.
So, what am I doing wrong, or, how could I adapt the version with the setter to return an array, std::string[]? My goal is to have an alternative to a global variable, that has only one instance in memory no matter how many calls.
Here's an adapted code, from a small program, on how I would build a menu using struct with enum and string (menu_design = new QMenu... and menuDesignAction() is the function that updates):
for(unsigned char i=0; i<A::ALL; ++i) // needs initializing
{
QAction *tmpAction {new QAction(tr(A::names[i].c_str()))};
tmpAction->setObjectName(QString("%1").arg(i));
connect(tmpAction, SIGNAL(triggered(bool)), this, SLOT(menuDesignAction()));
menu_design->addAction(tmpAction);
}
As a side-note, in the snippet above, I have to use .c_str(), but I am using a std::string in the enum. If I could make it *char[] instead of std::string[], would I avoid extra calls? If I am not wrong, how could the answers to my problem (assuming there are) be adapted so as to be able to fit somehow in the Qt snippet?
My program uses a Random class which manages a generator type and provides templated functions to return distributions using the given generator. However, when I compile it I invariably get undefined reference errors.
To illustrate the problem I've created a simple program which contains a Random class that simply provides a templated function Random::f() which returns a normally distributed number:
#include <random>
#include <iostream>
class Random
{
public:
template <typename T>
static T f()
{
std::normal_distribution<T> distribution(0,1);
return distribution(generator);
}
static std::default_random_engine generator;
};
int main()
{
std::cout << Random::f<double>();
return 0;
}
When I compile this using gcc 4.9.2 I get:
quant#900AX:~/Documents$ echo $CC
/usr/bin/gcc-4.9
quant#900AX:~/Documents$ $CXX -std=c++11 main.cpp
/tmp/ccWCPiN7.o: In function `double Random::f<double>()':
main.cpp:(.text._ZN6Random1fIdEET_v[_ZN6Random1fIdEET_v]+0x2b): undefined reference to `Random::generator'
collect2: error: ld returned 1 exit status
Why am I getting this error?
Put the definition out of the class:
std::default_random_engine Random::generator;
The code you have written, just declares the member object, you have to write a definition for it.
Static data members declarations in the class declaration are not definition of them.
Provide a definition to generator as its a static variable.
std::default_random_engine Random::generator = std::default_random_engine();
I have a function, that when defined in the main file of my program, works as I wish, and produces a lot of undefined references, when defined in a header file.
This header file exists:
#include "Domain.h"
#include "Character.h"
class Item {
public:
Character input;
Item(Character c2);
};
Item pistol(int which, float strength);
The function that makes problems is pistol. It looks like
Item pistol(int which, float strength) {
Interval i = Interval(0, 1);
Domain d = Domain(i);
Character c = Character({d}, {1});
return Item(c);
}
When I try to link the code with my main program, all calls that refer to object in Domain.h and Character.h are undefined references, that means I get linking time errors like:
undefined reference to `Character::show()'
...
undefined reference to `Interval::Interval(float, float)'
...
these errors are at places in the code, which are not inside the pistol function.
When I move this function to my main program, everything works as expected:
#include "Domain.h"
#include "Character.h"
#include "Item.h"
Item pistol(int which, float strength) {
// definition, see above
}
int main() {
Item w2 = pistol(2, 0.5);
return 0;
}
What is the problem with that function being in Item.h/Item.cxx?
What do I need to do to put it their?
undefined reference is a linking stage error.
You most probably missed to link with a compilation unit, missed to recompile a dependent compilation unit, or tried to have a template class/function definition not seen by the compiler from all your compilation units using it!
I can't find bug in this code
In function `BinaryCode::decode(std::string)':
undefined reference to `BinaryCode::m_vecStr'
undefined reference to `BinaryCode::m_vecStr'
undefined reference to `BinaryCode::m_vecStr'
undefined reference to `BinaryCode::m_vecStr'
undefined reference to `BinaryCode::m_vecStr'
more undefined references to `BinaryCode::m_vecStr' follow
http://codepad.org/PtZkGx6W
output is in above site:
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
using namespace std;
class BinaryCode{
public:
BinaryCode(void);
~BinaryCode(void);
static vector<string> m_vecStr;
vector<string> decode(string message);
};
BinaryCode::BinaryCode(void){
}
BinaryCode::~BinaryCode(void){
}
vector<string> BinaryCode::decode(string message){
m_vecStr.clear();
char szNone[]={"NONE"};
m_vecStr.push_back(szNone);
m_vecStr.push_back(message);
return m_vecStr;
}
int main(){
BinaryCode bc;
//cout<<bc.decode("12310122");
return 0;
}
You must define the static member outside of the class declaration. Try adding this after the class declaration:
vector<string> BinaryCode::m_vecStr;
If you're declaring your class in a distinct file, make sure you define the static members in the implementation file (generally .cpp), not in the header file (.h).
It is not a bug it is a linker error which tells you that linker cannot find definition for m_vecStr.
You need to define a static variable, in your code you just declared it but forgot to define it.
Add the following definition:
vector<string> BinaryCode::m_vecStr;
only once in your source file.
I am attempting to develop a class with a function that can take a vector of items as it's argument.
I can get it to work fine if I use a vector of type int, or other primitive, but I can't get it to work with a vector of objects.
eg:
In my header file:
int influenceParticles(vector<Particle> particles);
This is what I am after, but won't compile (error stated is "'Particle' was not declared in this scope").
The particle.h file has been included at the top of this header file.
Clarification
Here is the .h file that gives me the error
#ifndef _PARTICLE_ATTRACTOR
#define _PARTICLE_ATTRACTOR
#include "ofMain.h"
#include "particle.h"
class ParticleAttractor {
//private
public:
ParticleAttractor(int posX, int posY); //constructor (void)
int influenceParticles(vector<Particle> particles);
};
#endif
Maybe you have cyclic includes, ie. if the ParticleAttractor.h also includes the Particle.h. To solve this, you should make a forward declaration of Particle in ParticleAttractor.h:
class Particle;
You should also consider passing the vector by reference to avoid copying:
int influenceParticles(vector<Particle>& particles);
First Particle must be a defined type. This definition should work:
int influenceParticles(vector<vector<int> > particles);
For practice, it is better to use the by reference parameter type rather than by value. So it is better to define it as:
int influenceParticles(vector<vector<int> >& particles);