Error compiling simple program

So, I actually have two questions, which relate to similar code. On trying to figure out the first problem I unwarily found a different issue which I don't understand. This code is based on a quiz from a C++ tutorial, and I'm trying to understand the code rather than just get the right quiz answer. (which I already know anyway).

So, the first piece of code is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int z=1;

class ABC {
public:
    static int a;
    ABC(){a=1; z++;}
};

int main(void) {
    cout << z << endl;
return 0;
}

... and this compiles and outputs 1 as the result. I understand why it outputs 1, which is because z doesn't actually get altered anywhere, as no objects get created, etc. But, two things with this:

(a) the z declaration has nothing to do with the class, so I'm curious why the code compiles when the class has no z variable of its own (but it references z++). I'd have thought it would fail, but it doesn't.

(b) even if I do create an object, the value of z remains as 1, when I would have imagined it should be 2 (after the constructor does the z++ code).

So, in an effort to figure this out I was playing around with the code and came up with this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

int z=1;

class ABC {
public:
    static int a;
    ABC(){a=1; z++;}
    int getZ(){return z;};
};

int main(void) {
    ABC obj();  // with or without () fails to compile
    cout << obj.getZ << endl;
return 0;
}


… but trying to compile this gives me "error: request for member 'getZ' in 'obj', which is of non-class type 'ABC()'". I've tried compiling both with and without the parentheses, but I get a whole bunch of different error messages if I try to compile without ().

Confused! Any assistance and helpful explanations appreciated. Thanks in advance!
Last edited on
z is a global variable. Reachable from everywhere. Including inside a class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

int z=1;

class ABC {
public:
    static int a;
    ABC(){a=1; z++;}
    int getZ(){return z;};
};

int ABC::a;  // You have to create static variables somewhere. 

int main() {
    ABC obj;
    cout << obj.getZ() << endl; // You forgot how to call a function
return 0;
}

z is global, which is very bad practice. Globals are mostly recognized by being outside of all scopes (a scope is loosely defined as a {} pair, like inside main).

because it is global, the class can see it, change it, use it, etc. And, even more strange, if you had 5 variables of your class type (ABC a,b,c,d; in other words) then all of those would use the SAME z variable. If you want to do that, the better way is a static class member, which is shared across all class variable instances but not global.

More in a moment.


This is what I think you were trying to do. It prints the expected 2 for z. your static a was wrong, that isnt how it is done in a class. do you need to see this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

int z=1;

class ABC {
public:
     int a;
    ABC(){a=1; z++;}
    int getZ(){return z;};
};

int main(void) {
    ABC obj;  // with or without () fails to compile
    cout << obj.getZ() << endl;
return 0;
}

Last edited on
Okay, I understand why z is reachable then. But in that case I'd have expected z to be incremented (using the first piece of code which does compile), yet it isn't.

Not quite sure about why you create "int ABC::a" as "a" is already created inside the class.

Okay, yeah, with "obj.getZ()" missing the brackets I'd just been playing around trying to get it working; I should have put the brackets back again before posting.

Anyway, thanks for that, appreciated; but the code still fails to compile because of the "obj.getZ()" line even using the proper function call with "()", with the error as mentioned.

So, still curious about the second part of the first question, and still curious about what is preventing the second piece of code from compiling.
Last edited on
it is incremented. I ran the fixed one I gave you (which only made changes to make it compile) and z is 2 as expected.

the code I gave compiles. there were some little changes, look closer or run what I gave you in the forum's compiler.

What was wrong with it mostly was static a member is incorrect, and the () on the function call.

you can also fix the static a.

class ABC {
public:
static int a; //i removed static instead of fixing it.
ABC(){a=1; z++;}
int getZ(){return z;};
};
int ABC::a; //this was missing
Last edited on
Not quite sure about why you create "int ABC::a" as "a" is already created inside the class.


No, it is not created there. A static class member is NOT created along with an instance of the class. You must create it yourself.

1
2
3
4
5
class A
{
  int a; // one of these will be created every time an instance of class A is created
  static int b; // this will NOT be created when an instance of class A is created. You must create it yourself
}


The code I wrote compiles fine.
Sorry jonnin, I was actually replying to the post above yours, as I hadn't seen yours at that point.

Yeah, the original code (as per the first example) is just copied from the original problem, so it's not my code. I'm not sure it's meant to be especially good code, rather code designed to trick people a little doing the quiz.

Okay, so I can see that your code outputs 2, (which is what I figured it should be), and you've changed the static int to a plain old int, and it works just fine. I also note Repeater's code (thx), where he defines "a" outside of the class with "int ABC::a;" which also works. However …. (excuse my ignorance!) …

… and going back to a slightly modified version of the first piece of code, and now I create an object, I'd have still expected z to be 2, but it isn't. How come? After all, z starts life at 1, and creating the object surely invokes the constructor which then increments z by 1, so (in my beginners mind) it should be 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int z=1;

class ABC {
public:
    int a;
    ABC(){a=1; z++;}
};

int main(void) {
    ABC obj();
    cout << z << endl;
return 0;
}

Also, just curious; so you got rid of the "static" from the "a" variable in the class, and it works just fine; and you didn't need to create the variable anywhere else. The other poster instead maintained it as a static variable but then declared it outside of the class, and that also worked. When you declare a variable as static in that way, in a class, must you always then define it elsewhere too?

I really appreciate your time and effort. Thanks!
Last edited on
ABC obj();This does NOT create an ABC object. This is a function declaration. It is declaring that a function exists, named obj, that accepts no parameters and returns an ABC object.

I expect you meant this:
ABC obj;
Last edited on
yes, the right way to do a static class variable is to have the extra statement outside the class body. Its a lot to go into the why, it has to do with how the compiler deals with static variables and what static does under the hood. I am not sure I could explain it fully; you may want to find a 2-3 page answer on google if you want to see why.

check this one out:
1
2
3
4
5
6
int main(void) {
    ABC::a = 3; //with the static version of a, of course. 
    cout << z << endl;
return 0;
}


so with NO variables of type ABC, no class instances, it can still see the variable from the class. Static is powerful, but it also can cause threading nightmares and many of the same issues caused by global variables. Use it wisely.
Last edited on
Thank you both (jonnin and Repeater) very much. I think I understand at least a bit more now.

Repeater: Yeah, "ABC obj;" does indeed work properly, as expected. Thx.

jonnin: okay; I'll endeavor to get my head around static a bit more, but I appreciate the intro'!

Thanks again!

Topic archived. No new replies allowed.