由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - in-class static member question
相关主题
c++ 弱问题:static const char* const 这两个const 分别是什么意思?问一个 char * 和 char [] 的问题
[合集] 为什么 const member 不能是 static.[合集] static const代替define的performance tradeoff在哪里?
c++ 一问static initialization dependency c++
What're the three types of memory allocated for C++ variables?c++ 不自动initialize变量么?
A question about c++ pointerquestion about const reference
C++一个string的小问题How to initialize object in constructor?
谁给解释一下这个c question error LNK2001:的错误如何改正?
c++面试问题odr-used
相关话题的讨论汇总
话题: static话题: definition话题: int话题: char话题: const
进入Programming版参与讨论
1 (共1页)
g*********s
发帖数: 1782
1
The following code has compilation errors if "-DDEBUG" is not specified.
In function `StripePainter::init_tab(std::basic_string std::char_traits, std::allocator >)':
inclass_static.cpp:(.text+0xb): undefined reference to
`StripePainter::colorset'
inclass_static.cpp:(.text+0x1b): undefined reference to
`StripePainter::orig_color'
inclass_static.cpp:(.text+0x23): undefined reference to
`StripePainter::colorset'
inclass_static.cpp:(.text+0x58): undefined reference to
`StripePainter::colorset'
collect2: ld returned 1 exit status
My question is why the static const int colorset_sz has no problem while
static const char orig_color and static set colorset must be
declared
again outside the class definition?
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class StripePainter {
public:
int minStrokes(string stripes);
private:
static const char orig_color = 'A' - 1;
static const int colorset_sz = 'Z' - 'A' + 1;
static void init_tab(string stripes);
static vector > > tab;
static set colorset;
static void print_tab();
static int ch2idx(char ch) { return ch - orig_color;}
static char idx2ch(int idx) { return orig_color + idx;}
};
vector > > StripePainter::tab;
#ifdef DEBUG
set StripePainter::colorset;
const char StripePainter::orig_color;
#endif
void StripePainter::init_tab(string stripes) {
colorset.clear();
colorset.insert(orig_color);
for ( int i = 0; i < stripes.size(); ++ i ) {
colorset.insert(stripes[i]);
}
if ( !tab.empty() ) {
for ( int i = 0; i < tab.size(); ++ i ) {
for ( int j = 0; j < tab[i].size(); ++ j ) {
tab[i][j].clear();
}
}
}
tab.resize(stripes.size() + 1);
for ( int i = 0; i < tab.size(); ++ i ) {
tab[i].resize(stripes.size());
for ( int j = 0; j < tab[i].size(); ++ j ) {
tab[i][j].resize(colorset_sz, INT_MAX);
}
}
}
int main (int argc, const char* argv[]) {
if ( argc != 2 ) {
return -1;
}
}
X****r
发帖数: 3557
2
9.4.2 Static data members
2 The declaration of a static data member in its class
definition is not a definition and may be of an incomplete
type other than cv-qualified void. A definition shall be
provided for the static data member if it is used in the
program.
...
4 If a static data member is of const integral or const
enumeration type, its declaration in the class definition
can specify a constant-initializer which shall be an
integral constant expression. In that case, the member
can appear in integral constant expressions within its
scope. The member shall still be defined in a namespace
scope if it is used in the program and the namespace scope
definition shall not contain an initializer.

specified.

【在 g*********s 的大作中提到】
: The following code has compilation errors if "-DDEBUG" is not specified.
: In function `StripePainter::init_tab(std::basic_string: std::char_traits, std::allocator >)':
: inclass_static.cpp:(.text+0xb): undefined reference to
: `StripePainter::colorset'
: inclass_static.cpp:(.text+0x1b): undefined reference to
: `StripePainter::orig_color'
: inclass_static.cpp:(.text+0x23): undefined reference to
: `StripePainter::colorset'
: inclass_static.cpp:(.text+0x58): undefined reference to

g*********s
发帖数: 1782
3
so const char is not considered as const integral type?

【在 X****r 的大作中提到】
: 9.4.2 Static data members
: 2 The declaration of a static data member in its class
: definition is not a definition and may be of an incomplete
: type other than cv-qualified void. A definition shall be
: provided for the static data member if it is used in the
: program.
: ...
: 4 If a static data member is of const integral or const
: enumeration type, its declaration in the class definition
: can specify a constant-initializer which shall be an

e****d
发帖数: 895
4
what kind of compiler do you use? static const char should be
able to define in class.

【在 g*********s 的大作中提到】
: so const char is not considered as const integral type?
b*****e
发帖数: 474
5
const char is not const integral type in g++

【在 e****d 的大作中提到】
: what kind of compiler do you use? static const char should be
: able to define in class.

g*********s
发帖数: 1782
6
yes i'm using g++ 4.4.3.
so "static const char orig_char = '@'" in the class definition is not a
definition but a declaration, according to 2nd floor's comments?
if so what is the definition and what is the declaration for variables?
isn't the one with the initializer a definition?
totally confused here.

【在 b*****e 的大作中提到】
: const char is not const integral type in g++
g*********s
发帖数: 1782
7
in addition, why static const integral type needs such a special
treatment? it is really challenging to remember all of these special
cases.

【在 g*********s 的大作中提到】
: yes i'm using g++ 4.4.3.
: so "static const char orig_char = '@'" in the class definition is not a
: definition but a declaration, according to 2nd floor's comments?
: if so what is the definition and what is the declaration for variables?
: isn't the one with the initializer a definition?
: totally confused here.

e****d
发帖数: 895
8
My gcc 4.4.5 doesn't have any problem to define static const char variable
in class.

【在 b*****e 的大作中提到】
: const char is not const integral type in g++
b*****e
发帖数: 474
9
strange. I am using gcc/g++ 4.4.1 and the problem is still there.

【在 e****d 的大作中提到】
: My gcc 4.4.5 doesn't have any problem to define static const char variable
: in class.

e****d
发帖数: 895
10
You can always define static class data members outside the class.
This specifical case just gives you some convinience.

【在 g*********s 的大作中提到】
: in addition, why static const integral type needs such a special
: treatment? it is really challenging to remember all of these special
: cases.

相关主题
C++一个string的小问题问一个 char * 和 char [] 的问题
谁给解释一下这个c question[合集] static const代替define的performance tradeoff在哪里?
c++面试问题static initialization dependency c++
进入Programming版参与讨论
g*********s
发帖数: 1782
11
why it is "defined" out of the class while "declared" in the class?
i thought the outside one was declared, while the inside one is defined.
how do we distinguish "declared" and "defined" variables through some rule
of thumb?
for function it's very clear. but for variables, i'm totally lost now.

【在 e****d 的大作中提到】
: You can always define static class data members outside the class.
: This specifical case just gives you some convinience.

e****d
发帖数: 895
12
Declaration allows name lookup to find the entity.
Definition defines the entity.
A definition can also be a declaration.
You declare a static data member in a class and define it outside the class.
One definition rule doesn't allow you define a static data member
in a class becuase multiple includes will violate the ODR.

【在 g*********s 的大作中提到】
: why it is "defined" out of the class while "declared" in the class?
: i thought the outside one was declared, while the inside one is defined.
: how do we distinguish "declared" and "defined" variables through some rule
: of thumb?
: for function it's very clear. but for variables, i'm totally lost now.

g*********s
发帖数: 1782
13
sorry, i'm more confused.
1. the initializer should go with declaration or definition, or it
doesn't matter?
it's ok to have:
a.cpp: int x = 0; // definition.
b.cpp: extern int x; // declaration.
but is it ok to have the following?
a.cpp: int x; // definition.
b.cpp: extern int x = 0; // declaration.
2. why definition of a static variable in a class violates the ODR?
because we can define a static integral variable in a class, it seems
not a problem to allow any static variable to be defined in the class,
doesn't it?
4. why it's OK to have a definition of a function in a class? b/c
function definitions are "static" in the nature, aka, the code is shared
by all objects of this class?

class.

【在 e****d 的大作中提到】
: Declaration allows name lookup to find the entity.
: Definition defines the entity.
: A definition can also be a declaration.
: You declare a static data member in a class and define it outside the class.
: One definition rule doesn't allow you define a static data member
: in a class becuase multiple includes will violate the ODR.

e****d
发帖数: 895
14
extern int x = 0 is a definition.
Initializer means definition.
When you define a function inside a class, it's inline, which
doesn't violate the ODR.
If there are two translation units and each of them include
the class with a static data member defined in the class,
there will be two instances of this static data member in
the program, which violates ODR. const integral data member
is a special case, by which the compiler might just put the
member inside the class definition.

【在 g*********s 的大作中提到】
: sorry, i'm more confused.
: 1. the initializer should go with declaration or definition, or it
: doesn't matter?
: it's ok to have:
: a.cpp: int x = 0; // definition.
: b.cpp: extern int x; // declaration.
: but is it ok to have the following?
: a.cpp: int x; // definition.
: b.cpp: extern int x = 0; // declaration.
: 2. why definition of a static variable in a class violates the ODR?

t****t
发帖数: 6806
15
actually, most things in c++ are definitions (thus also declarations).
the several cases that are declarations ONLY are:
* extern, without initializer
* function w/o body
* class/struct forward declaration
* typedef
* using
* static data member inside a class (this is where are you confused)

【在 g*********s 的大作中提到】
: sorry, i'm more confused.
: 1. the initializer should go with declaration or definition, or it
: doesn't matter?
: it's ok to have:
: a.cpp: int x = 0; // definition.
: b.cpp: extern int x; // declaration.
: but is it ok to have the following?
: a.cpp: int x; // definition.
: b.cpp: extern int x = 0; // declaration.
: 2. why definition of a static variable in a class violates the ODR?

N***m
发帖数: 4460
16
最怕记这些东西了,头疼!

【在 t****t 的大作中提到】
: actually, most things in c++ are definitions (thus also declarations).
: the several cases that are declarations ONLY are:
: * extern, without initializer
: * function w/o body
: * class/struct forward declaration
: * typedef
: * using
: * static data member inside a class (this is where are you confused)

P********e
发帖数: 2610
17
你记它做什么

【在 N***m 的大作中提到】
: 最怕记这些东西了,头疼!
N***m
发帖数: 4460
18
得熟练阿,而且面试的时候也可能会问到。
唉,我也真够无聊的。

【在 P********e 的大作中提到】
: 你记它做什么
t****t
发帖数: 6806
19
people often found that c++ has a lot of things to remember. but in fact, if
you know the reason behind them, there is actually very little to "remember
".
For example, in this case, there is only one thing to remember, which is "
one definition rule".
* extern: if you declare it extern, you most probably have definition
elsewhere. so the one with extern is not definition. however if there is
initializer, then this must be the definition, since only one initializer is
allowed.
* function w/o body: this is obvious. you must have body "defined" somewhere
else.
* forward declaration: same as function header.
* typedef: this only introduce an alias.
* using: same, alias
* static data member: class definition is meant to be included in multiple
files. if static data member is definition, then one definition rule is
violated. therefore you must defined it ("again") somewhere else.
In fact, if you know how the linker (link editor) works, then one definition
rule is a natural corollary. You don't even have to remember that.

【在 N***m 的大作中提到】
: 最怕记这些东西了,头疼!
b*****e
发帖数: 474
20
这一段:
* static data member: class definition is meant to be included in multiple
files. if static data member is definition, then one definition rule is
violated. therefore you must defined it ("again") somewhere else.
- 这个 #include 不是问题吧, 用 #ifndef 。。。 #define 。。。#endif
保证了只一次的

if
remember
is
somewhere

【在 t****t 的大作中提到】
: people often found that c++ has a lot of things to remember. but in fact, if
: you know the reason behind them, there is actually very little to "remember
: ".
: For example, in this case, there is only one thing to remember, which is "
: one definition rule".
: * extern: if you declare it extern, you most probably have definition
: elsewhere. so the one with extern is not definition. however if there is
: initializer, then this must be the definition, since only one initializer is
: allowed.
: * function w/o body: this is obvious. you must have body "defined" somewhere

相关主题
c++ 不自动initialize变量么? error LNK2001:的错误如何改正?
question about const referenceodr-used
How to initialize object in constructor?c++ class definition
进入Programming版参与讨论
t****t
发帖数: 6806
21
one definition rule means you define only once in MULTIPLE compilation units
.
#ifdef guard let you include a file only once in ONE compilation unit.
why a lot of people mix them? they are totally unrelated.

【在 b*****e 的大作中提到】
: 这一段:
: * static data member: class definition is meant to be included in multiple
: files. if static data member is definition, then one definition rule is
: violated. therefore you must defined it ("again") somewhere else.
: - 这个 #include 不是问题吧, 用 #ifndef 。。。 #define 。。。#endif
: 保证了只一次的
:
: if
: remember
: is

g*********s
发帖数: 1782
22
so if i define a class w/ static variable members in foo.h, i'll have to
create a foo.cpp file to keep the definitions of these static variables,
instead of put these definitions in foo.h?

fact, if
"remember
is "
is
initializer is
somewhere

【在 t****t 的大作中提到】
: people often found that c++ has a lot of things to remember. but in fact, if
: you know the reason behind them, there is actually very little to "remember
: ".
: For example, in this case, there is only one thing to remember, which is "
: one definition rule".
: * extern: if you declare it extern, you most probably have definition
: elsewhere. so the one with extern is not definition. however if there is
: initializer, then this must be the definition, since only one initializer is
: allowed.
: * function w/o body: this is obvious. you must have body "defined" somewhere

t****t
发帖数: 6806
23
of course. any c++ textbook will mention this.

【在 g*********s 的大作中提到】
: so if i define a class w/ static variable members in foo.h, i'll have to
: create a foo.cpp file to keep the definitions of these static variables,
: instead of put these definitions in foo.h?
:
: fact, if
: "remember
: is "
: is
: initializer is
: somewhere

g*********s
发帖数: 1782
24
haha, never read through a c++ textbook, as the thickness always scares
me...

【在 t****t 的大作中提到】
: of course. any c++ textbook will mention this.
e****d
发帖数: 895
25
How about static data member of templates?
Isn't it defined during implicit/explicit instantiation?
Which compilation unit is responsible for it if
multiple compilation units are using it?

units

【在 t****t 的大作中提到】
: one definition rule means you define only once in MULTIPLE compilation units
: .
: #ifdef guard let you include a file only once in ONE compilation unit.
: why a lot of people mix them? they are totally unrelated.

b*****e
发帖数: 474
26
But, for integral types, you can put static definitions there.
I think that's why LZ asked about the exception. That's something
in addition to the one definition rule.

【在 t****t 的大作中提到】
: of course. any c++ textbook will mention this.
t****t
发帖数: 6806
27
didn't you read xentar's post? even you can write initializer to const
integral static data member, it doesn't mean you don't have to write
separate definitons.
however, in most cases, const static integral will be optimized out as
constant, and there will be no references to the symbol anymore in the link
stage. and in compilation stage, "no diagnostic required" (9.4.2 clause 5),
so in most cases you can get through without any errors. BUT, i can easily
construct a counter-example:
#include
class A {
public:
static const int a=5;
};
int main()
{
std::cout<<&A::a; // if you comment this line you can pass
}
By referencing the address of A::a, I force the compiler to allocate an
address for symbol A::a (i.e. I force the existence of symbol), thus
requires the definition of A::a. constant integral static data member is not
an exception of ODR.

【在 b*****e 的大作中提到】
: But, for integral types, you can put static definitions there.
: I think that's why LZ asked about the exception. That's something
: in addition to the one definition rule.

t****t
发帖数: 6806
28
template is really the "exception" of ODR. Because template is basically
macro of c++ version (i.e. you have to follow c++ syntax and semantics), it
requires a "full definition" wherever you want to instantiate it; on the
other hand, ODR requires only one definition across multiple files. so in
the real world, template requires the special support of link editor to trim
down the extra copies of the same function in multiple files. for example,
GNU ld for ELF target uses "weak symbol" for template functions, and
multiple weak symbols are not considered multiple definition. other models
exists, too.

【在 e****d 的大作中提到】
: How about static data member of templates?
: Isn't it defined during implicit/explicit instantiation?
: Which compilation unit is responsible for it if
: multiple compilation units are using it?
:
: units

b*****e
发帖数: 474
29
You are right & your example is great. Thanks.
But I was referring to the fact that, given:
class A {
public:
const static int a = 1;
const static char c = 'A';
};
You definitely need to define const char A::c; in your code,
but you don't need to write const int A::a; (there is danger
of not writing this, as you have pointed out).
In other words, it seems that const static int typically will be optimized
out, but const static char does not get this treatment.
ODR notwithstanding, I see there is a difference. I think your point
is, just write the definition ALWAYS.

link
,

【在 t****t 的大作中提到】
: didn't you read xentar's post? even you can write initializer to const
: integral static data member, it doesn't mean you don't have to write
: separate definitons.
: however, in most cases, const static integral will be optimized out as
: constant, and there will be no references to the symbol anymore in the link
: stage. and in compilation stage, "no diagnostic required" (9.4.2 clause 5),
: so in most cases you can get through without any errors. BUT, i can easily
: construct a counter-example:
: #include
: class A {

t****t
发帖数: 6806
30
not sure what version you use, but in g++ 4.4.4 they are the same.

【在 b*****e 的大作中提到】
: You are right & your example is great. Thanks.
: But I was referring to the fact that, given:
: class A {
: public:
: const static int a = 1;
: const static char c = 'A';
: };
: You definitely need to define const char A::c; in your code,
: but you don't need to write const int A::a; (there is danger
: of not writing this, as you have pointed out).

相关主题
static vector 怎么 initialize ?[合集] 为什么 const member 不能是 static.
关于C/C++里的Static variable的memory allocation/initializac++ 一问
c++ 弱问题:static const char* const 这两个const 分别是什么意思?What're the three types of memory allocated for C++ variables?
进入Programming版参与讨论
g*********s
发帖数: 1782
31
4.4.3 not the same. so a bug fixed in 4.4.4?
it is said 4.4.5 ok too but 4.4.1 not.

【在 t****t 的大作中提到】
: not sure what version you use, but in g++ 4.4.4 they are the same.
1 (共1页)
进入Programming版参与讨论
相关主题
odr-usedA question about c++ pointer
c++ class definitionC++一个string的小问题
static vector 怎么 initialize ?谁给解释一下这个c question
关于C/C++里的Static variable的memory allocation/initializac++面试问题
c++ 弱问题:static const char* const 这两个const 分别是什么意思?问一个 char * 和 char [] 的问题
[合集] 为什么 const member 不能是 static.[合集] static const代替define的performance tradeoff在哪里?
c++ 一问static initialization dependency c++
What're the three types of memory allocated for C++ variables?c++ 不自动initialize变量么?
相关话题的讨论汇总
话题: static话题: definition话题: int话题: char话题: const