Rationale for Static Member Definition in ISO C++

Z

ziman137

Hi all,

I have a question here. What is the rationale behind ISO C++ for
Static Member Definition?

* ISO C++ forbids in-class definition/initialization of non-constant
static member variables.

For example, instead of

class Fred {
public:
Fred();
...
private:
static int N = 0;
};

it must be defined as

int Fred::N = 0;

* However, a static member function can be defined in-class (or,
inline).

What is(are) the problem(s) with in-class static member variable
initialization? Would appreciate any input and help.

Gary
 
I

Ian Collins

ziman137 said:
Hi all,

I have a question here. What is the rationale behind ISO C++ for
Static Member Definition?

* ISO C++ forbids in-class definition/initialization of non-constant
static member variables.

For example, instead of

class Fred {
public:
Fred();
...
private:
static int N = 0;
};
When would the initialisation take place? A static member isn't bound
to any instance of the class.

Where as

static const int N = 0;

Can be initialised at compile time.
 
Z

ziman137

Ian said:
When would the initialisation take place? A static member isn't bound
to any instance of the class.

Where as

static const int N = 0;

Can be initialised at compile time.

Yes, this rationale makes sense. Yet, a static member function isn't
bound to any instance of the class, either. We can still legally define
static member functions as follows,

class Fred {
public:
Fred();
static void do() { //... };
...
};

Reversely we may say that, as defined
class cls
{
...
private:
static int N = 0;
}
in the class, we could also initialize "cls::N" as a global-like
member, recognized by the tag "static". Not quite sure anyway.

Thanks,
Gary
 
I

Ian Collins

ziman137 said:
Yes, this rationale makes sense. Yet, a static member function isn't
bound to any instance of the class, either. We can still legally define
static member functions as follows,

class Fred {
public:
Fred();
static void do() { //... };
...
};
Code, which is no different form any other code and doesn't require
initialisation.
Reversely we may say that, as defined
class cls
{
...
private:
static int N = 0;
}
in the class, we could also initialize "cls::N" as a global-like
member, recognized by the tag "static". Not quite sure anyway.
There still has to one an instance of it somewhere. That somewhere
would be in each compilation unit that sees the class, so you would end
up with multiple instances of cls::N.

If you have in a header (outside of a class),

int N = 0;

each compilation unit that includes the header will have its own locally
scoped N.

If you have

extern int N;

N is a global with only a single instance and a single definition.

A static class member has to have global scope and exist only once, so
the same rules apply as the extern int above. This is a somewhat
counter intuitive use of 'static'.
 
M

Maxim Yegorushkin

ziman137 said:
Yes, this rationale makes sense. Yet, a static member function isn't
bound to any instance of the class, either. We can still legally define
static member functions as follows,

Think of it this way. A static member variable is essentially an extern
variable that should be defined somewhere, a static member function is
an inline function if defined in the class definition.
 
B

benben

Yes, this rationale makes sense. Yet, a static member function isn't
bound to any instance of the class, either. We can still legally define
static member functions as follows,

class Fred {
public:
Fred();
static void do() { //... };
...
};

Wow, slow down and think again! Even a non-static member function isn't
bound to any instance of the class. The only difference between a static
member function and a non-static member function is that the latter
takes an extra (hidden) parameter (the this pointer.)

So there is *no* difference in *storage* between a static member
function and a non-static member function.

But there is a storage distinction between a static and a non-static
member variable, right?

Regards,
Ben
 
Z

ziman137

Thanks guys!
Wow, slow down and think again! Even a non-static member function isn't
bound to any instance of the class. The only difference between a static
member function and a non-static member function is that the latter
takes an extra (hidden) parameter (the this pointer.)

Yes, this is a good point. Do you mean that, "this" points to somewhere
partly containing only the stack for local variables, return addresses?
So, for static member function, "this" key word is invalid (true).
 
M

Maxim Yegorushkin

ziman137 said:
Thanks guys!

Yes, this is a good point. Do you mean that, "this" points to somewhere
partly containing only the stack for local variables, return addresses?

Yes, for some compilers (gcc) this is passed through stack along with
other arguments.

Consider the output of the following illegal code:

[max@localhost exp]$ cat exp.cpp
#include <stdio.h>

struct S
{
void foo() { printf("%s: this=0x%p\n", __PRETTY_FUNCTION__, this);
}
};

int main()
{
union
{
void(S::*m)();
void(*f)(S*);
} u = { &S::foo };

S s;
s.foo();
u.f(&s);
}

[max@localhost exp]$ g++ --version
g++ (GCC) 4.1.0 20060304 (Red Hat 4.1.0-3)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

[max@localhost exp]$ g++ -Wall -Wextra exp.cpp -o exp

[max@localhost exp]$ ./exp
void S::foo(): this=0x0xbfb8a007
void S::foo(): this=0x0xbfb8a007
 
Z

ziman137

Maxim said:
Yes, this is a good point. Do you mean that, "this" points to somewhere
partly containing only the stack for local variables, return addresses?

Yes, for some compilers (gcc) this is passed through stack along with
other arguments.

Consider the output of the following illegal code:

[max@localhost exp]$ cat exp.cpp
#include <stdio.h>

struct S
{
void foo() { printf("%s: this=0x%p\n", __PRETTY_FUNCTION__, this);
}
};

int main()
{
union
{
void(S::*m)();
void(*f)(S*);
} u = { &S::foo };

S s;
s.foo();
u.f(&s);
}

[max@localhost exp]$ g++ -Wall -Wextra exp.cpp -o exp
[max@localhost exp]$ ./exp
void S::foo(): this=0x0xbfb8a007
void S::foo(): this=0x0xbfb8a007

This is because the only syntax for pointing to a member function is
"&Class::FunctionName()" - I got it. In above code, if we
change the "foo" to the static, all bets are off with not only "this",
but also any other non-static members. This tells me that, a static
member function is really a global function!(?) May we conclude
as below?

/* a static member is simply a global variable/function, with its class
** name as the scope qualifier - equivalent to a namespace way.
*/

By the way, what's the illegal part of above codes?

Thanks much,
Gary
 
M

Maxim Yegorushkin

ziman137 said:
Maxim said:
Yes, this is a good point. Do you mean that, "this" points to somewhere
partly containing only the stack for local variables, return addresses?

Yes, for some compilers (gcc) this is passed through stack along with
other arguments.

Consider the output of the following illegal code:

[max@localhost exp]$ cat exp.cpp
#include <stdio.h>

struct S
{
void foo() { printf("%s: this=0x%p\n", __PRETTY_FUNCTION__, this);
}
};

int main()
{
union
{
void(S::*m)();
void(*f)(S*);
} u = { &S::foo };

S s;
s.foo();
u.f(&s);
}

[max@localhost exp]$ g++ -Wall -Wextra exp.cpp -o exp
[max@localhost exp]$ ./exp
void S::foo(): this=0x0xbfb8a007
void S::foo(): this=0x0xbfb8a007

This is because the only syntax for pointing to a member function is
"&Class::FunctionName()" - I got it. In above code, if we
change the "foo" to the static, all bets are off with not only "this",
but also any other non-static members.

I could not understand the last sentence. Sorry.
This tells me that, a static
member function is really a global function!(?) May we conclude
as below?

/* a static member is simply a global variable/function, with its class
** name as the scope qualifier - equivalent to a namespace way.
*/

Global is not the same as class scope. A static member function is a
function with external linkage within the scope of ist class.
By the way, what's the illegal part of above codes?

Casting a pointer to (nonstatic) member function to a (regular)
function pointer is UB.
 
Z

ziman137

Maxim said:
I could not understand the last sentence. Sorry.

In my last sentence, I mean, if we define "foo()" as a static member

struct S
{
static void foo1() { // ... };
};

in foo() definition body, it is not allowed to access pointer "this"
and any other non-static members. It is not bound to any "S" object -
otherwise there would be unresolvable ambiguity about "this" pointer in
foo() when we have two different "S" objects. In that sense, "foo()" is
encapsulated in class "S" scope ONLY for the sake of its namespace.
When you say, global and class scope is not the same, I agree upon the
sense of namespace. Beyond the namespace, the static "foo()" is
otherwise just like a global function. Would you agree?

Thanks,
Gary
 
M

Maxim Yegorushkin

ziman137 said:
In my last sentence, I mean, if we define "foo()" as a static member

struct S
{
static void foo1() { // ... };
};

in foo() definition body, it is not allowed to access pointer "this"
and any other non-static members. It is not bound to any "S" object -
otherwise there would be unresolvable ambiguity about "this" pointer in
foo() when we have two different "S" objects. In that sense, "foo()" is
encapsulated in class "S" scope ONLY for the sake of its namespace.
When you say, global and class scope is not the same, I agree upon the
sense of namespace. Beyond the namespace, the static "foo()" is
otherwise just like a global function. Would you agree?

I would.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top