I need to access m[] in c.cpp from d.cpp. The array m[] is a member of CD within a namespace and is declared in c.h within that class. So I declare a static array s[] in the same class CD in the file c.h. Instantiate it in c.cpp and use a function to copy the elements of the original array m[] to static arrays[]. Then, I #include "c.h" in d.cpp where I need to access it.
c.h
namespace k{
class CD {
string m[10];
static string s[10];
}}
c.cpp
#include "c.h"
namespace k{
string CD::s[10] = {"q"}
}
d.cpp
#include "c.h"
void func(){
string n = k::CD::s[0];
}
But I am getting an error saying undefined reference to k::CD::s.
Am I doing something wrong here? Or is there some other way of doing this?
Some notes:
c.h
#ifndef C_H_HEADER_GUARD // add header guard
#define C_H_HEADER_GUARD
#include <string> // you need this header
namespace k {
class CD {
// string is in the "std" namespace, so:
std::string m[10]; // note that this is private!
// "s" can't be private since you want to access it outside the class, in `func()`:
public:
static std::string s[10];
}; // class definitions need to end with ;
} // namespace k
#endif
c.cpp
#include "c.h" // enclose the header with quotation marks
namespace k {
using namespace std; // in here it's ok to use namespace std:
string CD::s[10] = {"q"}; // missing ;
} // namespace k
d.cpp
#include "c.h" // again, quotation marks
void func() {
std::string n = k::CD::s[0]; // missing std::
}
Now, this will compile the two translation units into c.o and d.o that you can use when linking with the TU containing main later.
g++ -c c.cpp d.cpp -Wall -Wextra -pedantic -pedantic-errors
Since d.cpp doesn't have a d.h declaring the function func though, you'll need to declare that where you want to use it. Not nice, but:
void func();
Related
I have the following code structure composed of one .cpp, one .cu and one .hxx
UTILITIES.hxx
#ifndef UTILITIES_HXX
#define UTILITIES_HXX
namespace B{
extern int doors;
}
FILE2.cu
#include "utilities.hxx"
namespace A {
int foo (){
switch(B::doors){
//do something
}
}
}
FILE3.cxx
#include "utilities.hxx"
namespace B{
int doors=-1;
class Vehicle{
public:
void operation() {
doors++;
A::foo();
doors++;
A::foo();
}
}
}
I am declaring the doors variable as extern in the header and I am defining it in the .cxx file. So after that, the second .cpp should be able to use it. However I am getting the following error when linking:
/usr/bin/ld: ../src/libapp.a(FILE2.cu.o): in function A::foo(void)': /MYPATH/FILE2.cu:19: undefined reference to B::doors'
What am I doing wrong? Actually the foo function in the FILE2.cu is a normal C++ function, no CUDA involved at all.
missing #endif, missing return statement, no prototype for A::foo(), missing semicolon
These changes seem to work for me:
$ cat utilities.hxx
#ifndef UTILITIES_HXX
#define UTILITIES_HXX
namespace B{
extern int doors;
}
#endif
$ cat file2.h
namespace A {
int foo ();
}
$ cat file2.cu
#include "utilities.hxx"
namespace A {
int foo (){
switch(B::doors){
//do something
}
return 0;
}
}
$ cat file3.cpp
#include "utilities.hxx"
#include "file2.h"
namespace B{
int doors=-1;
class Vehicle{
public:
void operation() {
doors++;
A::foo();
doors++;
A::foo();
}
};
}
$ nvcc -shared file2.cu file3.cpp -Xcompiler -fPIC
$ nvcc -lib file2.cu file3.cpp
$
I can only work with what you have shown.
I've got two files, list.cpp and Header.h. Segments of the files are below. I know that if the header file is for a class, it is setup different. E.g.
class MyClass
{
public:
void foo();
int bar;
};
However, since I'm not really working with a class here (correct me if I'm wrong), am I not able to declare things under public: and private like below?
Also, if I were to place the global variable rescan in the header file as a member variable, below the function definitions, only the main function can see the variable. Why is it not within the scope of the other functions?
list.cpp:
#include <boost/algorithm/string.hpp>
#include <vector>
using namespace std;
vector<int> results;
bool rescan;
int main()
{
vector<vector<string>> list;
int success = readFile(list);
vector<vector<string>> bad = findMe(list);
system("pause");
return 0;
}
vector<vector<string>> findMe(vector<vector<string>> find)
{
rescan = true;
}
Header.h:
#pragma once
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
#include <string>
#include <vector>
std::vector<std::vector<std::string>> findMe(std::vector<std::vector<std::string>>);
#endif
EDIT: I tried this in my header file:
public:
bool rescan;
But I got "syntax error: 'public'
If you want your global to be visible in other translation units (TU) (other files), you have to declare them extern in those other TUs:
Header.h:
// Include guard omitted
extern bool rescan; // Declaration
file.cpp
#include "Header.h"
bool rescan = false; // Definition
// ...
file2.cpp
#include "Header.h" // To see extern bool rescan;
void foo()
{
rescan = true;
}
// ...
As a preface, I'm using eclipse c++ as an IDE. And I'm using the c++0x11 standard. (So I can use mutex's) I'm very new to C++ but have done some C before and am very familiar with Java programming. Also, I know .h is usually not a type for C++ files.
I'm trying to include a private object member of stellad::KeyHook in my class stellad::Dispatcher and I get the following errors when building:
Building file: ../src/KeyHook.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/KeyHook.d" -MT"src/KeyHook.d" -o "src/KeyHook.o" "../src/KeyHook.cpp"
In file included from ../src/KeyHook.h:10:0,
from ../src/KeyHook.cpp:8:
../src/Dispatcher.h:23:11: error: ‘KeyHook’ in namespace ‘stellad’ does not name a type
stellad::KeyHook keyhook;
^
src/subdir.mk:21: recipe for target 'src/KeyHook.o' failed
make: *** [src/KeyHook.o] Error 1
A lot of lines have been removed to reduce noise, such as unnecessary includes, prototypes and function declarations.
Dispatcher.h
/*
* Dispatcher.h
*/
#ifndef DISPATCHER_H_
#define DISPATCHER_H_
#include "KeyHook.h"
namespace stellad {
class Dispatcher {
private:
..
stellad::KeyHook keyhook;
public:
Dispatcher();
virtual ~Dispatcher();
..
};
} /* namespace stellad */
int main(int argc, const char* argv[]);
#endif /* DISPATCHER_H_ */
KeyHook.h
/*
* KeyHook.h
*/
#ifndef KEYHOOK_H_
#define KEYHOOK_H_
#include "Dispatcher.h"
namespace stellad {
class KeyHook{
private:
..
public:
KeyHook();
virtual ~KeyHook();
..
};
} /* namespace stellad */
#endif /* KEYHOOK_H_ */
It's caused by each file including the other.
If the first included is KeyHook.h, then before any declarations it includes Dispatcher.h. That includes KeyHook.h again but it finds that KEYHOOK_H_ is already defined and does not declare anything. Then the headers look like this:
// #include "KeyHook.h" from KeyHook.cpp
// #define KEYHOOK_H_
// #include "Dispatcher.h" from KeyHook.h
// #define DISPATCHER_H_
// #include "KeyHook.h" from Dispatcher.h
// KEYHOOK_H_ already declared
// end of #include "KeyHook.h" from Dispatcher.h
namespace stellad {
class Dispatcher {
private:
..
stellad::KeyHook keyhook; // KeyHook not declared here
public:
Dispatcher();
virtual ~Dispatcher();
..
};
} /* namespace stellad */
int main(int argc, const char* argv[]);
// end of #include "Dispatcher.h" from KeyHook.h
namespace stellad {
class KeyHook{
private:
..
public:
KeyHook();
virtual ~KeyHook();
..
};
} /* namespace stellad */
To solve this, you need to break the cyclic inclusion. KeyHook does not require Dispatcher, simply remove #include "Dispatcher.h" from it.
You have a circular include problem. Remove the #include "Dispatcher.h" from KeyHook.h. You may need to add a forward declaration class Dispatcher; instead.
I got three .cpp files and two header files.
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Below is my Data.h(previously known as 2.h at above)
#include <iostream>
#include <string>
using namespace std;
class Data
{
private:
string sType;
public:
Data();
Data(string);
void setSType(string);
string getSType();
};
Below is my data.cpp
#include "Data.h"
Data::Data()
{
sType = "";
}
Data::Data(string s)
{
sType = s;
}
void Data::setSType(string ss)
{
sType = ss;
}
string Data::getSType()
{
return sType;
}
Below is my PointD.h (previously known as 3.h)
#include <iostream>
#include <string>
#include "Data.h"
using namespace std;
class PointD
{
private:
int x
Data data1;
public:
PointD();
PointD(int,Data);
void setX(int);
void setData(Data);
int getX();
Data getData();
};
Below is my PointD.cpp
#include "PointD.h"
PointD::PointD()
{
x = 0;
}
PointD::PointD(int xOrdinate,Data dd)
{
x = xOrdinate;
data1 = dd;
}
void PointD::setXordinate(int Xordinate)
{
x = Xordinate;
}
void PointD::setData(Data dd)
{
data1 = dd;
};
int PointD::getXordinate()
{
return x;
}
Data PointD::getData()
{
return data1;
}
This is my main.cpp
#include <iostream>
#include <string>
#include "Data.h"
#include "PointD.h"
using namespace std;
int main()
{
const int MAX_NUM = 20;
Data ldata[MAX_NUM];
PointD pointd[MAX_NUM];
//more codes..
}
But when i compile them, meaning the Point.cpp, Data.cpp and main.cpp, it will say
Data.h:6:7 redefinition of Data at 'Data.h'
Data.h:6:7 previously definition of 'class Data'
Can anybody let me know whats actually went wrong here..
You need to use include guards, or the easiest:
#pragma once
in your header files
See Purpose of Header guards for more background
Idea: 1.hpp
#ifndef HEADER_GUARD_H1_HPP__
#define HEADER_GUARD_H1_HPP__
// proceed to declare ClassOne
#endif // HEADER_GUARD_H1_HPP__
In each of your header files write:
#ifndef MYHEADERNAME_H
#define MYHEADERNAME_H
code goes here....
#endif
Its better like this:
#ifndef DATA_H /* Added */
#define DATA_H /* Added */
#include <iostream>
#include <string>
// using namespace std; /* Removed */
class Data
{
private:
std::string sType;
public:
Data();
Data( std::string const& ); // Prevent copy of string object.
void setSType( std::string& ); // Prevent copy of string object.
std::string const& getSType() const; // prevent copy on return
std::string& getSType(); // prevent copy on return
};
#endif /* DATA_H */
The big fix is adding ifndef,define,endif. The #include directive works as if copying and pasting the .h to that line. In your case the include from main.cpp are:
main.cpp
-> Data.h (1)
-> Point.h
-> Data.h (2)
At (2), Data.h has already been `pasted' into main.cpp at (1). The class declaration of Data, i.e. "class Data{ .... };" , appears twice. This is an error.
Adding include guards to the top and bottom of every .h are standard practice to avoid this problem. Don't think about it. Just do it.
Another change I'd suggest is to remove any "using namespace ..." lines from any .h . This breaks the purpose of namespaces, which is to place names into separate groups so that they are not ambiguous in cases where someone else wants an object or function with the same name. This is not an error in your program, but is an error waiting to happen.
For example, if we have:
xstring.h:
namespace xnames
{
class string
{
...
};
}
Foo.h
#include <xstring>
using namespace xnames;
...
test.cxx:
#include "Foo.h"
#include "Data.h" // Breaks at: Data( string ); -- std::string or xnames::string?
...
void test()
{
string x; // Breaks. // std::string or xnames::string?
}
Here the compiler no longer knows whether you mean xnames::string or std::string. This fails in test.cxx, which is fixable by being more specific:
void test()
{
std::string x;
}
However, this compilation still now breaks in Data.h. Therefore, if you provide that header file to someone, there will be cases when it is incompatible with their code and only fixable by changing your header files and removing the "using namespace ...;" lines.
Again, this is just good coding style. Don't think about it. Just do it.
Also, in my version of Data.h, I've changed the method parameters and return types to be references (with the &). This prevents the object and all of its state from being copied. Some clever-clogs will point our that the string class's is implementation prevents this by being copy-on-write. Maybe so, but in general, use references when passing or returning objects. It just better coding style. Get in the habit of doing it.
Consider the following example. It consists of two header files, declaring two different namespaces:
// a1.h
#pragma once
#include "a2.h"
namespace a1
{
const int x = 10;
typedef a2::C B;
}
and the second one is
// a2.h
#pragma once
#include "a1.h"
namespace a2 {
class C {
public:
int say() {
return a1::x;
}
};
}
And a single source file, main.cpp:
#include <iostream>
#include "a1.h"
#include "a2.h"
int main()
{
a2::C c;
std::cout << c.say() << std::endl;
}
This way it doesn't compile (tried GCC and MSVC). The error is that a1 namespaces is not declared (C2653 on Windows). If you change include order in main.cpp this way:
#include "a2.h"
#include "a1.h"
you get a symmetric error message, i.e. a2 namespace is not declared.
What's the problem?
You need to use a forward declaration in your header files because you have a circular reference. Something like this:
// a1.h
#pragma once
namespace a2 {
class C;
}
namespace a1
{
const int x = 10;
typedef a2::C B;
}
Just a guess, but your include reference is circular. Meaning the compiler can't figure out which header to compile first. a1 references a2 which references a1.
If possible, merge/reorganize the files so that there is a non-circular chain of includes.
Hope that helps!
When you include a1.h first, it immediately tries to include a2.h before declaring anything
a2.h references something in namespace a1 that hasn't been declared yet
When you include a2.h first, it immediately tries to include a1.h before declaring anything
a1.h references something in namespace a2 that hasn't been declared yet
Removing the typedef from a1.h, which you aren't using, and not including a2.h removes the cycle.
Or as by the other commenter, forward declare class C.
// a1.h
#pragma once
//#include "a2.h"
namespace a1
{
const int x = 10;
// typedef a2::C B;
}