This question already has answers here:
C++ Multiple classes with same name
(5 answers)
Closed 6 years ago.
I have three files, main.cpp, a.cpp and b.cpp. The main() function just calls a function in a.cpp, and then in b.cpp -- and I get a SIGSEGV. As far as I can tell, it looks like the lambda functions used with my sort() are conflicting with each other. Compile command line order is important; if I compile the files via:
g++ -std=c++11 main.cpp a.cpp b.cpp
The code crashes (I get "*** stack smashing detected ***: ./a.out terminated"), but if I switch "a.cpp" and "b.cpp":
g++ -std=c++11 main.cpp b.cpp a.cpp
it runs fine (I'm not saying anything about whether it "works" or not, just SIGSEGV vs no-SIGSEGV).
Here's the smallest code samples I could generate for the three files:
main.cpp:
extern void spud1 (void);
extern void spud2 (void);
int
main (int argc, char **argv)
{
spud1 ();
spud2 ();
}
a.cpp:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct Database
{
int pubdate;
string title;
string link;
};
static vector <Database> database;
void
spud1 (void)
{
int i;
for (i = 0; i < 20; i++) {
database.push_back ({});
}
sort(database.begin(), database.end(),
[] (const Database& a, const Database& b)
{
return (a.pubdate > b.pubdate);
});
}
b.cpp:
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct Database
{
unsigned serial;
double calories;
double carbs;
double sodium;
double sugar;
};
static vector <Database> database;
void
spud2 (void)
{
int i;
for (i = 0; i < 20; i++) {
database.push_back ({});
}
sort(database.begin(), database.end(),
[] (const Database& a, const Database& b)
{
return (a.serial > b.serial);
});
}
There are two things that bother me about this:
there's no indication from the toolchain that "something bad" is happening; there are no compiler or linker warnings, and
I have no way to make "struct Database" local to the module -- if I stick "static" in front of it I get an error: "a.cpp:13:1: error: a storage class can only be specified for objects and functions**`"
So, my question is, what am I doing wrong, and how can I get around it? (i.e., why is there no warning, is this "supposed" to happen? and how do I make my "Database" struct actually be local to the module? -- my workaround is to use different names, but I'm not happy with that.)
You can make the struct declarations/definitions private for the translation unit by putting them into an unnamed namespace:
namespace { // <<<<<<<<<<<<<<<<
struct Database
{
unsigned serial;
double calories;
double carbs;
double sodium;
double sugar;
};
}
Otherwise the linker will use what's found first, no matter if your lambda functions are module local as well.
That was learned from that same subtle bug, we spent on debugging 3 or 4 days in our production code. Not funny, no.
Related
I have a file named test.cc
#include <stdio.h>
int doit(){
return 4;
}
namespace abc {
int returnIt(int a){
return a;
}
}
I can use doit(), but how can I use this function in namespace in my main.cc without using .h file:
using namespace abc;
int doit();
int main(int argc, const char * argv[]) {
cout<<returnIt(3)<<endl; // print 3
cout<<doit(); // print 4
return 0;
}
You can call functions by first declaring them. Example:
namespace abc {
int returnIt(int a); // function declaration
}
int main() {
abc::returnIt(3); // the declared function can now be called
Note that the declaration must be exactly the same as used elsewhere in the program. To achieve identical declarations across translation units, it is conventional to put the declaration into a separate file (called a header) and include that file using the pre-processor whenever the declaration is needed.
All you need is to simply write the functions before the main function. That way, the compiler has processed the function prototypes by the time it encounters them in main and can validate the function call.
int doit()
{
return 4;
}
int returnIt(int a)
{
return a;
}
int main(int argc, const char * argv[])
{
cout<<returnIt(3)<<endl; // print 3
cout<<doit(); // print 4
return 0;
}
In general, avoid using namespace;. It makes for code that can be broken or be rendered less readable due to incorrect variable/function usage. That is because too many symbols can occupy the same (global) scope.
If another library needs to used, as user4581301 pointed out, then it may be simpler to use eerorika answer/method.
I have these two files table.cpp and table.h in my program code apart from the main.cpp. The files are described as below
table.cpp
#include <iostream>
#include "table.h"
using namespace std;
// accessor function for Name
char* PeriodicTable::Name()
{
return Name;
}
// accessor function for Symbol
char* PeriodicTable::Symbol()
{
return Symbol;
}
table.h
#ifndef TABLE_H
#define TABLE_H
class PeriodicTable
{
char Name[15], Symbol[3], GroupName[20], Block, State[25], Colour[15], Classification[20];
int GroupNo, AtomicNo, PeriodNo;
float Weight;
public:
char* Name();
char* Symbol();
};
#endif
but the problem is that the IntelliSense(since I am using Visual C++ Express 2010) shows a red curved underline below the name and symbol in the accessor function in table.cpp. I can't understand why???
Your member functions and member variables have the same name. This is not possible in C++. That's why various conventions exist for naming member variables, e.g. m_name, name_ etc. (NB: When dealing with underscores in identifiers make sure you don't use a reserved name by accident.)
You might wonder why and how that could possibly go wrong. In your example there clearly is no way to invoke operator() on char[15], but the problem is that the compiler only knows that after performing semantic analysis. There could also be cases where it is impossible to disambiguate. For example:
struct Func {
void operator()() { };
};
struct C {
Func f;
void f() {}
};
int main() {
C c;
c.f(); // which one?
}
I am having trouble understanding c++ namespaces. Consider the following example:
//distr.h
namespace bogus{
extern const int x;
extern const int y;
double made_up_distr(unsigned param);
}
Now if I define my variables like the cpp below everything compiles fine
//distr.cpp
#include "distr.h"
#include <cmath>
const int bogus::x = 10;
const int bogus::y = 100;
double bogus::made_up_distr(unsigned param){
auto pdf = (exp(param) / bogus::x) + bogus::y;
return pdf;
}
But if I try to simply bring in the bogus namespace and use instead
//broken distr.cpp
#include "distr.h"
#include <cmath>
using namespace bogus;
const int x = 10;
const int y = 100;
double made_up_distr(unsigned param){
auto pdf = (exp(param) / x) + y;
return pdf;
}
My compiler tells me that the reference to x and y is ambiguous.
Why is that?
There's a simple reason why this can't plausibly work the way you expected:
namespace bogus {
const int x;
}
namespace heinous {
const int x;
}
using namespace bogus;
using namespace heinous;
const int x = 10;
now, should x above refer to bogus::x, heinous::x or a new global ::x?
It would be the third without the using statements, which means here that adding a using statement would change the meaning of existing code in a particularly subtle way.
The using statement is used to introduce the contents of a scope (usually but not necessarily a namespace) for lookup. The statement
const int x = 10;
wouldn't normally require a lookup in the first place, except to detect an ODR violation.
Name lookup for the identifier in declarations/definitions doesn't work the same way as name lookup in usage. In particular, it doesn't care about using statements. There is a very simple reason for this: if it were different, it would lead to all sorts of nasty surprises. Consider this:
// sneakattack.h
namespace sneakattack { void foo(); }
using namespace sneakattack;
// somefile.cpp
#include "sneakattack.h"
void foo() { std::cout << "Hello\n"; }
// otherfile.cpp
void foo();
int main() { foo(); }
This program currently works: the declaration sneakattack::foo is ignored, and the definition ::foo is correctly linked to the use in otherfile. But if name lookup worked differently, somefile would suddenly define sneakattack::foo, not ::foo, and the program would fail to link.
Hi I am trying to understand the scope of friend functions and I get a "not declared in scope" error. Here is my code:
//node.h
class Node{
public:
int id;
int a;
int b;
friend int add(int,int);
void itsMyLife(int);
Node();
};
//node.cpp
Node::Node(){
a=0;
b=0;
id=1;
}
void Node::itsMyLife(int x){
cout<<"In object "<<id<<" add gives "<<add(x,a)<<endl;
}
//routing.cpp
#include "node.h"
int add(int x, int y){
return x+y;
}
//main.cpp
#include "node.h"
int main(){
return 0;
}
I get the error "add not declared in this scope" in node.cpp. Why do I get this error when I have declared the function in the class scope? Any help will be appreciated. Thanks
Inside your node class you declare a friend function int add (int, int). However, currently the compiler hasn't encountered the function yet and therefore it is unknown.
You could make a separate header and source file for your add function. Then in node.h include you new header. Because in the file where you declare Node the function add is not known currently.
So you might make a add.h and a add.cpp file for example and include add.h before declaring Node. Don't forget to compile add.cpp as well.
Its a bug on the the Linux side. The code should work. I have code right now that compiles fine on the Windows side and when I move it to the Linux side I get the same error. Apparently the compiler that you are using on the Linux side does not see/use the friend declaration in the header file and hence gives this error.
By simply moving the of the friend function's implementation in the C++ file BEFORE that function's usage (e.g.: as might be used in function callback assignment), this resolved my issue and should resolve yours also.
Best Regards
You haven't actually declared the function.
extern int add(int, int);
#include "node.h"
#include <iostream>
using namespace std;
class Node{
public:
int id;
int a;
int b;
friend int add(Node &a);
void itsMyLife(int);
Node();
};
//node.cpp
Node::Node(){
a=0;
b=0;
id=1;
}
void Node::itsMyLife(int x):b(x){
cout<<"In object "<<id<<" add gives "<<add(Node &a)<<endl;
}
//routing.cpp
#include "node.h"
int add(Node &a){
return a.b+a.y;
}
//main.cpp
int main(){
Node n;
n.ItsMyLife(15);
cout<<add(n);
return 0;
}
This should work fine - I guess. The syntax for "friend" function is -- friend {returntype} {functionname} (class_name &object_name). To access any of the members of the class use object_name.variable_name.
I am writing a simple test program on Linux system by using g++ 4.3 and Rogue Wave library. The problem that I am facing here is that the following codes can be compiled but it would pop up a segmentation fault on this line when I run it:
_aClasses.insertKeyAndValue(100,1000);
When I run the same piece code on a HPUX machine by using aCC compiler. It runs smoothly which makes me confused. Is that because the way that g++ initialize the static variable is different from aCC does? Anyone knows what's going on here? Thanks in advance.
A.hxx
#include <rw/tvhdict.h>
#include <rw/cstring.h>
#include <rw/rwdate.h>
#include <rw/rstream.h>
using namespace std;
class A
{
public :
A();
static void add();
struct long_hash {
unsigned long operator() (const long& x) const { return x;};
};
struct long_equal {
RWBoolean operator() (const long& x, const long& y) const { return x==y;};
};
private:
static RWTValHashMap<long, long, long_hash, long_equal> _aClasses;
};
A.cxx
#include "A.hxx"
RWTValHashMap<long, long, A::long_hash, A::long_equal> A::_aClasses;
A::A()
{
cout<<"init A"<<endl;
}
void A::add()
{
_aClasses.insertKeyAndValue(100,1000);
}
B.hxx
class B
{
public:
B();
};
B.cxx
#include "B.hxx"
#include "A.hxx"
B::B()
{
A::add();
}
Main.cxx
#include "A.hxx"
#include "B.hxx"
static B c;
int main() {
cout<<"main"<<endl;
return 0;
}
The order of initialization of static members from different translation units (essentially different cpp/cxx files) is not specified. So whether static B c or RWTValHashMap<long, long, A::long_hash, A::long_equal> A::_aClasses will be initialized first can be different for different compilers and may even change when using the same compiler. It was simply luck that your previous compiler always initialized them in the desired order.
A way to avoid this is to use the 'construct on first use idiom'