My lecturer asked a question that I can't find its satisfactory answer. Quote from him " Just tell me a sentence why cannot static functions(methods) access to non-static data members? " Could you tell me why? I want to learn.
static method can be called on the class itself, no instance of that class is necessary.
This means that there is no instance of the class and so non-static data members have not been created and initialized.
You can call static methods using the syntax ClassName::MethodName().
In this case you are not accessing an concrete object and hence you can not
access non-static members.
Consider the following code:
class C {
public:
C(int i) { _i = i; }
int getI() { return _i; } // ok
/* error: using non-static member in a static method */
static int sgetI() { return _i; }
private:
int _i;
};
int main(void) {
C c1(1);
C c2(2);
int n1 = c1.getI(); // ok, n1 = 1
int n2 = c2.getI(); // ok, n2 = 2
int n3 = C::sgetI(); // what? does not make sense!
}
static-method and static-members are common among the all the instances of class.
So when you try to access non-static data-members the compiler can't decide what is the memory address of that non-static data-member. Remember, class is just a template, while object is one who has the address and stores the data in that particular format defined in class.
Let's take an example :
for the sake of argument let's assume C++ static method allows us to access non-static data-members. Let's create a class named person with name as string data member and two methods get_name() and put_name()
class person
{
string name;
public :
void get_name(){cin >> name;}
static void put_name(){cout << name << "\n";}
};
Now writing the driver program...
int main()
{
person p1,p2;
p1.get_name(); // input : alice
p2.get_name(); // input : bob
person :: put_name();
return 0;
}
We can clearly observe after taking two names as inputs, when we call put_name() what output the compiler would give? alice, bob or NULL ? because static member function is not affiliated with any of object it can't decide what to give as an output.
So now maybe it is clear that why cannot static functions(methods) access to non-static data members?. If you got your answer hope you appreciate the effort.
Related
Suppose I have class B which gets a value 'v' in the constructor from another class A. How can I read this value from class C?
Class C will be instantiated on demand, but A has created B and passed the 'v' already. 'v' will change in every instantiation. I have tried to make 'v' static in Class B. Would it work? I could not implement it properly.
Class A {
public:
int* v;
B b1;
A(int* var) : v(var), b1(var) {};
}
How to access the same version of 'v' from a C class?
I can define B and C however I like in order to achieve the goal. But I cannot change A for that purpose.
You need a (public) static member
class A { //let's stick with your naming convention!
public:
static int a;
}
A::a = 4;
However allowing people to change A::a means that your program will probably end up relying on a global unencapsulated state... which is usually a sign of a bad design.
If you member was const however you are really relating a constant to your class, which is not so bad.
class A {
public:
static const int a = 4;
}
std::cout << "A:a is always " << A::a << std::endl;
EDIT BASED ON UPDATED QUESTION
If you require help with building a class I would recommend that you use a factory of some kind. If I understand your requirement you want to be able to inject a value into every class A and class B instance. This value "v" is based on a Class C.
So...
class C {
private:
// up to you where you implement the getUniqueNumberForNow function
// (global free function for example)
static const int v = getUniqueNumberForNow();
public:
static A createA(){
return A(v);
}
static B createB(){
return B(v);
}
}
The getUniqueNumberForNow() function just gets whatever your value should be. It will be then stored in class C and can be used during the creation of A an\or B. Now just make A and B's CTORs private and make C a friend of both and you will have only one way to create an A or B, and it will always use the correct value.
See NeilMonday's link in the comments below for info on friend classes.
Last thing is if you want to have the value change for every instantiation of A you can just do this in the factory:
static A createA(){
return A(getUniqueNumberForNow());
}
However if that is really what you want then just do this:
class A {
public:
A() : val (getUniqueNumberForNow()), b(B(val)){}
}
You cannot access a 'v' which has never passed to the class. Instead you can make a static copy of it as a member in your class A. It will update every time A is instantiated like this:
Class A {
public:
int* v;
static int* staticv;
...// Constructor etc
}
in your .cc code of A:
int* A::staticv;
...
A::staticv=this->v;
now any class can access to this value by:
A::staticv;
#include <iostream>
using namespace std;
class MyClass
{
private:
static int x;
static int calc(int a, int b)
{
cout << "chekcing !! ";
return b * a;
}
};
int MyClass::x = 1;
int main()
{
MyClass::calc(1,2);
MyClass::x += 3;
return 0 ;
}
Question : As far i know Static members are not a part of class , then why do we have a check of access specifier ?
Each static member is shared across all the instances of that class. So they don't belong to one particular class instance but they belong to the class itself.
Access specification rules are per class not per object
From above, it is logical that the access specification rules apply to static members.
Your confusion stems from the fact that if you check size of a class with static member there is no overhead dues to the presence of the static member. This behavior is correct. The static members do not contribute towards the size of the class but they are still a part of the class and the standard explicitly says so.
Reference:
9.4.2 Static data members:
§1:
A static data member is not part of the subobjects of a class. If a static data member is declared thread_local there is one copy of the member per thread. If a static data member is not declared thread_local there is one copy of the data member that is shared by all the objects of the class.
Is it possible to access non static data members outside their class? Say you have an example like the following. I know it does not make much sense as an example, but I just want to understand how to access a non static data member. If the following is compiled it generates an error:
C.h|70|error: invalid use of non-static data member ‘C::age’|
//C.h
class C{
public:
int age;
};
int getAge();
//C.cpp
C::C()
{
age = 0;
}
int getAge(){
return (C::age);
}
Non-static members are instance dependent. They are initialized when a valid instance is initialized.
The problem with your example is that, it tries to access a non-static member through the class interface without first initializing a concrete instance. This is not valid.
You can either make it static:
class C{
public:
static int age;
};
which requires you to also define age before using at runtime by: int C::age = 0. Note that value of C::age can be changed at runtime if you use this method.
Or, you can make it const static and directly initialize it like:
class C{
public:
const static int age = 0;
};
In this case, value of C::age is const.
Both of which will let you get it without an instance: C::age.
Without making it static, you would have to create a value:
Either an lvalue:
C c;
return c.age;
or an rvalue:
return C().age;
// or
return C{}.age;
The problem with your code is that you try to access the age member without creating an instance of the class. Non-static data members of a class are only accessible through an instance of the class, and in your case no instance is created.
The reason why you can't is because local variables are allocated at runtime onto the stack - you can obtain its position if you really wanted to with some inline asm but it would require some debugging to obtain the stack position and the later (after the function) you want to access it the more likely it will have long been overwritten by something else.
I was studying ns-3 tutorial. I cannot understand the following code snippet:
class MyObject : public Object
{
public:
static TypeId GetTypeId (void)
{
static TypeId tid = TypeId ("MyObject")
.SetParent (Object::GetTypeId ())
.AddConstructor<MyObject> ()
.AddTraceSource ("MyInteger",
"An integer value to trace.",
MakeTraceSourceAccessor (&MyObject::m_myInt))
;
return tid;
}
MyObject () {}
TracedValue<int32_t> m_myInt;
};
As I understand, MyObject::m_myInt is an access to non-static class member m_myInt from static method and & takes address of this member. This code is successfully compiled and executed. How can it be possible? What instance of class does the static method use?
Pointers to members can be pointers to either member methods or member variables and do not need an instance of a class to be declared or assigned. This does not mean you can do much without an instance, however. You still need an instance to use them. Consider the following code:
class A
{
public:
void SomeMethod();
int someVar;
};
void (A::*pSomeMethod)() = &A::SomeMethod; //Declares a member pointer to method and assigns
int A::*pSomeVar = &A::someVar; //Declares a member pointer to int variable and assigns
A a; //Defines an instance
(a.*pSomeMethod)(); //Uses an instance with the pSomeMethod member pointer.
int var = (a.*pSomeVar); //Uses an instance with the pSomeVar member pointer.
It is possible, and it allows for some pretty cool stuff.
How do I access a static member in a class with all static methods?
I want to have a group of related functions but also have some important data members initialized before any of these functions are called. I thought a class with only static members would be the way to go. Compiler in VS2008 doesn't like me trying to access "a".
Surely I'm missing something small but still very confused. :P
(Even without the invalid access of "a" the constructor isn't called when calling testMethod() from main.
class IPAddressResolver
{
private:
public:
static int a;
IPAddressResolver();
static void TestMethod();
};
IPAddressResolver::IPAddressResolver()
{
IPAddressResolver::a = 0;
cout << "Creating IPAddressResolver" << endl;
}
void IPAddressResolver::TestMethod()
{
cout << "testMethod" << endl;
}
You need to define your static data member outside of the function, like
class IPAddressResolver
{
private:
static int a;
IPAddressResolver();
public:
static void TestMethod();
};
int IPAddressResolver::a = 0;
void IPAddressResolver::TestMethod()
{
cout << "testMethod" << endl;
}
Your constructor is not called, since you don't create a new instance of the class. For a static utility class, you don't need instances, so you can omit the constructor altogether. Alternatively, you might want to declare it private to make it explicit that the class shall not be instantiated (see above).
Notes:
it is not recommended to use public fields in classes, so I turned a into private,
static utility classes are usually stateless, so if you need to have fields within your class, this maybe a sign that the class would better be a Singleton.
Somewhere outside of the class definition, you need to define and initialize your static data members associated with that class.
Easiest is just to put
int IPAddressResolver::a = 0;
in your IPAddressResolver.cpp file.
I want to have a group of related functions but also have some important data members initialized before any of these functions are called
Sounds to me like you want a Singleton, not a class with only static members.