473,325 Members | 2,828 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,325 software developers and data experts.

problem passing a static const int member by reference

I have a member static const int x defined in class Foo, and I'm passing
it by reference, and by value elsewhere (see the code below). Passing it
by value works, but by reference it doesn't: it thinks x is undefined.
Could someone explain what's going on here? Why can't I pass a static
const member by reference?

This is how I compile it:

g++ -g -Wall sample_main.C # g++ -v 4.0.1
/tmp/ccUJx59K.o(.gnu.linkonce.t._ZN3Foo12bad_functionER 3Bar[Foo::bad_function(Bar&)]+0xa): In function `Foo::bad_function(Bar&)':
/tmp/STATICCONST/sample_main.C:18: undefined reference to `Foo::x'
collect2: ld returned 1 exit status
#include <cstdlib>
using namespace std;

class Bar
{
public:
void good(const int a) {}
void bad(const int & a) {}
};
class Foo
{
public:
static const int x=0;

void good_function(class Bar & B){ B.good(x); }
void bad_function(class Bar & B) { B.bad(x); }
};

int main(int argc, char * argv[])
{
Foo F;
Bar B;

F.good_function(B);
F.bad_function(B);

return 0;
}
Sep 17 '05 #1
13 2554
Amadeus W. M. wrote:
....

class Foo
{
public:
static const int x=0;

void good_function(class Bar & B){ B.good(x); }
void bad_function(class Bar & B) { B.bad(x); }
};


Add this:

const int Foo::x;
Sep 17 '05 #2
Amadeus W. M. wrote:
I have a member static const int x defined in class Foo, and I'm passing
it by reference, and by value elsewhere (see the code below). Passing it
by value works, but by reference it doesn't: it thinks x is undefined.
Could someone explain what's going on here? Why can't I pass a static
const member by reference?


You can but the difference is that when you pass by value the compiler
substitutes the value 0 so storage for the actual variable is not
needed. But when you pass by reference you need an actual variable which
you have failed to declare (what is in the class is a definition not a
declaration).

You need to add the declaration to sample_main.C as Gianni showed.

john
Sep 17 '05 #3
John Harrison wrote:
Amadeus W. M. wrote:
I have a member static const int x defined in class Foo, and I'm passing
it by reference, and by value elsewhere (see the code below). Passing it
by value works, but by reference it doesn't: it thinks x is undefined.
Could someone explain what's going on here? Why can't I pass a static
const member by reference?

You can but the difference is that when you pass by value the compiler
substitutes the value 0 so storage for the actual variable is not
needed. But when you pass by reference you need an actual variable which
you have failed to declare (what is in the class is a definition not a
declaration).

You need to add the declaration to sample_main.C as Gianni showed.

john


Sorry, got the words definition and declaration completely the wrong way
round in the above explanation.

john
Sep 17 '05 #4
On Sat, 17 Sep 2005 11:14:56 -0700, Gianni Mariani wrote:
Amadeus W. M. wrote:
...

class Foo
{
public:
static const int x=0;

void good_function(class Bar & B){ B.good(x); }
void bad_function(class Bar & B) { B.bad(x); }
};


Add this:

const int Foo::x;


Of course, this works, but I thought only non-integer static consts
require this. I thought static const int can be defined inside the class.
And it can be defined inside the class, as long I don't pass it by
reference.
Sep 17 '05 #5
On Sat, 17 Sep 2005 18:22:51 +0000, John Harrison wrote:
Amadeus W. M. wrote:
I have a member static const int x defined in class Foo, and I'm passing
it by reference, and by value elsewhere (see the code below). Passing it
by value works, but by reference it doesn't: it thinks x is undefined.
Could someone explain what's going on here? Why can't I pass a static
const member by reference?
You can but the difference is that when you pass by value the compiler
substitutes the value 0 so storage for the actual variable is not
needed. But when you pass by reference you need an actual variable which
you have failed to declare (what is in the class is a definition not a
declaration).


But isn't x supposed to be _defined_ (hence allocated and initialized)
when I say

static const int x=0; // inside class Foo;

?? Is it that the compiler is trying to be smart, or am I not complying
with the standard?
You need to add the declaration to sample_main.C as Gianni showed.

john


Sep 17 '05 #6

"Amadeus W. M." <am*******@cablespeed.com> wrote in message
news:pa****************************@cablespeed.com ...
<snip>

#include <cstdlib>
using namespace std;

class Bar
{
public:
void good(const int a) {}
void bad(const int & a) {}
};
class Foo
{
public:
static const int x=0;

void good_function(class Bar & B){ B.good(x); }
void bad_function(class Bar & B) { B.bad(x); }
};

int main(int argc, char * argv[])
{
Foo F;
Bar B;

F.good_function(B);
F.bad_function(B);

return 0;
}

This code works fine under VS8 ;/
Sep 17 '05 #7
On Sat, 17 Sep 2005 14:23:44 -0500, Jon Slaughter wrote:

"Amadeus W. M." <am*******@cablespeed.com> wrote in message
news:pa****************************@cablespeed.com ...
<snip>

#include <cstdlib>
using namespace std;

class Bar
{
public:
void good(const int a) {}
void bad(const int & a) {}
};
class Foo
{
public:
static const int x=0;

void good_function(class Bar & B){ B.good(x); }
void bad_function(class Bar & B) { B.bad(x); }
};

int main(int argc, char * argv[])
{
Foo F;
Bar B;

F.good_function(B);
F.bad_function(B);

return 0;
}

This code works fine under VS8 ;/


Thank you, maybe I should ask on a g++ newsgroup then.
Sep 17 '05 #8
In fact, here's what I want to do: I have 1 header file Foo.H included in
two source files sample_main.C and foobar.C. The definition of Foo::x
should really be in Foo.H.
// file Foo.H:
#ifndef _FOO_H
#define _FOO_H

#include <cstdlib>
using namespace std;

class Bar
{
public:
void good(const int a) const {}
void bad(const int & a) const {}
};
class Foo
{
public:
static const int x=0;

void good_function(const Bar & B) const { B.good(x); }
void bad_function(const Bar & B) const { B.bad(x); }
};
const int Foo::x;

#endif

// file foobar.C:
#include <cstdlib>
#include "Foo.H"

using namespace std;

void foobar()
{
Foo F;
Bar B;

F.good_function(B);
F.bad_function(B);
}

// file sample_main.C
#include <cstdlib>
#include "Foo.H"

using namespace std;

extern void foobar();

int main(int argc, char * argv[])
{
Foo F;
Bar B;

F.good_function(B);
F.bad_function(B);

foobar();

return 0;
}

g++ sample_main.C foobar.C

gives (understandably) multiple definition of Foo::x. Of course, if I put
const int Foo::x;
in sample_main.C, it works, but I it's more natural that the definition of
Foo::x should be in Foo.H.

If I don't put const int Foo::x; anywhere (neither in main nor in Foo.H),
it works, as long as I don't call Foo::bad_function() i.e. as long as I
don't access Foo::x by reference.


If, on the other hand, I make Foo a template class and define

template <class DummyType>
const int Foo<DummyType>::x;

outside Foo in Foo.H, it works (no multiple definition of
Foo<DummyType>::x, no undefined references). I would rather not make Foo
a template class though, if I don't have to.

Is there another way? Thanks!

Sep 17 '05 #9
Amadeus W. M. wrote:
In fact, here's what I want to do: I have 1 header file Foo.H included in
two source files sample_main.C and foobar.C. The definition of Foo::x
should really be in Foo.H.
// file Foo.H:
#ifndef _FOO_H
#define _FOO_H

#include <cstdlib>
using namespace std;

class Bar
{
public:
void good(const int a) const {}
void bad(const int & a) const {}
};
class Foo
{
public:
static const int x=0;

void good_function(const Bar & B) const { B.good(x); }
void bad_function(const Bar & B) const { B.bad(x); }
};
const int Foo::x;

#endif

// file foobar.C:
#include <cstdlib>
#include "Foo.H"

using namespace std;

void foobar()
{
Foo F;
Bar B;

F.good_function(B);
F.bad_function(B);
}

// file sample_main.C
#include <cstdlib>
#include "Foo.H"

using namespace std;

extern void foobar();

int main(int argc, char * argv[])
{
Foo F;
Bar B;

F.good_function(B);
F.bad_function(B);

foobar();

return 0;
}

g++ sample_main.C foobar.C

gives (understandably) multiple definition of Foo::x. Of course, if I put
const int Foo::x;
in sample_main.C, it works, but I it's more natural that the definition of
Foo::x should be in Foo.H.
Well that is tough, C++ says it should be in sample_main.C (or foobar.C).

If I don't put const int Foo::x; anywhere (neither in main nor in Foo.H),
it works, as long as I don't call Foo::bad_function() i.e. as long as I
don't access Foo::x by reference.

That is true, although I'm not sure the C++ standard guarantees that.

If, on the other hand, I make Foo a template class and define

template <class DummyType>
const int Foo<DummyType>::x;

outside Foo in Foo.H, it works (no multiple definition of
Foo<DummyType>::x, no undefined references). I would rather not make Foo
a template class though, if I don't have to.

Well that is because the rules for templates are different. Template
code *always* goes in header files.
Is there another way? Thanks!


No, unless an enum would suffice.

class Foo
{
enum { x = 1 };
};

In the old days you would have been required to define and initialise
Foo::x in a .C file. Since standardisation you can now initialise Foo::x
in the header file, but you are still required to define it in a .C file.

john
Sep 17 '05 #10
Try adding #pragma once to the top of your foo.h, it seems that your
ifndef/define isn't working like you think. This fixed the problem for me.

As far as I could tell the compiler was parsing foo.h in foobar.c and
created the object Foo::x then tried to do it again in main.cpp.

By telling it only to parse it once solved the problem I had with multiple
link defines.

Jon
Sep 18 '05 #11

"Jon Slaughter" <Jo***********@Hotmail.com> wrote in message
news:11*************@corp.supernews.com...
Try adding #pragma once to the top of your foo.h, it seems that your
ifndef/define isn't working like you think. This fixed the problem for me.

As far as I could tell the compiler was parsing foo.h in foobar.c and
created the object Foo::x then tried to do it again in main.cpp.

By telling it only to parse it once solved the problem I had with multiple
link defines.

Jon


heh, nm, it stopped working after I build it again ;/ not sure whats going
on ;/
Sep 18 '05 #12

"Jon Slaughter" <Jo***********@Hotmail.com> wrote in message
news:11*************@corp.supernews.com...

"Jon Slaughter" <Jo***********@Hotmail.com> wrote in message
news:11*************@corp.supernews.com...
Try adding #pragma once to the top of your foo.h, it seems that your
ifndef/define isn't working like you think. This fixed the problem for
me.

As far as I could tell the compiler was parsing foo.h in foobar.c and
created the object Foo::x then tried to do it again in main.cpp.

By telling it only to parse it once solved the problem I had with
multiple link defines.

Jon


heh, nm, it stopped working after I build it again ;/ not sure whats going
on ;/


Its definately from it including foo twice.

Compiling...

foobar.cpp

c:\documents and settings\jon\my documents\visual studio
2005\projects\test3\test3\foo.h(32) : error C2720: 'Foo::x' : 'static '
storage-class specifier illegal on members

c:\documents and settings\jon\my documents\visual studio
2005\projects\test3\test3\foo.h(32) : error C2734: 'Foo::x' : const object
must be initialized if not extern

Generating Code...

Compiling...

main.cpp

c:\documents and settings\jon\my documents\visual studio
2005\projects\test3\test3\foo.h(32) : error C2720: 'Foo::x' : 'static '
storage-class specifier illegal on members

c:\documents and settings\jon\my documents\visual studio
2005\projects\test3\test3\foo.h(32) : error C2734: 'Foo::x' : const object
must be initialized if not extern

Generating Code...

Note, the simpliest code here seems to generate the error:

------------ Foo.h -------------

#pragma once

#ifndef _FOO_

#define _FOO_

class Bar

{

public:

void good(const int a) const { }

void bad(const int & a) const { }

};

class Foo

{

public:

static const int x = 3;

void good_function(const Bar &B) const { B.good(x); }

void bad_function(const Bar &B) const { B.bad(x); }

};

const int Foo::x;

#endif

------------- foobar.cpp -----------

#include "Foo.H"

void foobar()

{

int y = Foo::x;

};

---------- Main.cpp -----------

#include "Foo.H"

int main(int argc, char * argv[])

{

int y = Foo::x;

return 0;

}

Note that when I remove the const int Foo::x I have no problems with the
original code(B.bad works fine).

Jon
Sep 18 '05 #13
I guess we couldn't see the forest because of the trees. In this trivial
example it makes sense to implement everything in Foo.H, but, as we were
taught in school, we should really separate the interface (in Foo.H) from
the implementation (Foo.C). Then we could have const int Foo::x; in Foo.C,
and that will only be processed once. It's trivial, and it re-invents the
wheel, but it's another good, non-cosmetic reason to separate Foo.H from
Foo.C.

Sep 18 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: John Stiles | last post by:
I have written some pretty simple code which works great in Dev Studio and CodeWarrior, but gcc is giving me link errors. Here is what I've been able to distill it down to: namespace Private {...
8
by: Srini | last post by:
Hello all, I was just wondering about this. A const member function guarantees constness of the object within the function body. But there's no way for a member function to guarantee the...
17
by: Ashwin | last post by:
hi guys, i have overloaded the << operator.as shown below. ostream& operator<<(ostream &out, const student &a) { out<<a.idno; out<< " " ; // out<< a.name; out<< " " ; // out<< a.marks...
9
by: Gary Wessle | last post by:
Hi in the attempt below, I intend to use 2 derived classes whose objects c'tor fires a base class method which build a string "main_menu" which is a concatenation of the strings for each derived...
18
by: tbringley | last post by:
I am a c++ newbie, so please excuse the ignorance of this question. I am interested in a way of having a class call a general member function of another class. Specifically, I am trying to...
18
by: mati | last post by:
Hi The following code works: #include <vector> class C { private: static const int m_static = 2; public: void f(const std::vector<int>& v)
3
by: Bram Kuijper | last post by:
Hi all, I am trying to resize a vector of objects (MyObj below), which contain references to other objects (OtherObj, see below). However, apparently somewhere in the resize operation an...
3
by: Subodh | last post by:
Hi All, In C++ we could pass a constant reference to a function so that the target function could not modify the objects passed eg. const classA & dummmyfunction(const classB) similar thing...
4
by: puzzlecracker | last post by:
How can I pass a reference to a method as constant? I tried the following: Function(const Foo f) or Function(readonly Foo f) Also, How to declare local variable to be constant const...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.