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.
Related
I've encountered this code example and I remembered I've seen it before and I didn't know what it is for and what it does? I've searched on the internet but without luck.
Code:
class C
{
int x; // a non-static variable, implicitly private
public:
C() : x(0) {} // default constructor
// a static member function, which uses a non-static variable perfectly well
static int Incr(C& instance) { return ++(instance.x); }
} g_c;
int main(void)
{
C c2;
return C::Incr(g_c) + C::Incr(c2);
}
What does g_c after the last class bracket means?
} g_c;
Here g_c is declared to be an object of the class type C.
Such construct enables you to create object(s) of unnamed type as:
class //Nameless class!
{
//data members
}obj1, obj2;
In this example, obj1 and obj2 are declared to be objects of a class type which has not been given any name — the class is nameless! In such situation, you cannot declare objects in a conventional sense (i.e Type obj1, obj2; sense). So this construct helps you do that.
You can even derive from other named classes while being nameless (and declaring the objects of the nameless class):
class : public A, public B //Nameless class is deriving from A and B
{
//data members
}obj1, obj2;
In short, this construct ensures that the user wouldn't be able to create more objects than intended, unless some evil programmer uses/misuses/abuses C++11 (or template) as:
decltype(obj1) obj3; //hehe!
Hope that helps!
It's shorthand for:
class C
{
....
};
C g_c;
You declare variables using the format type variable_name;. For example:
A x;
Where A may be the name of a class.
But instead of using a pre-existing class type, you can also define the class at the same time as you declare a variable of the new class's type:
class { ... } x;
or define the class and give it a name:
class A { ... } x;
In C++ it is common to just define the class and give it a name, but leave off the variable:
class A { ... };
but you don't have to leave off the variable.
That's just a way of creating objects of that type of Class. Structs mostly use them to initialize new variables.
I've come across an exam question with this abstract class template definition:
template <class MusicPlayer>
class SongAbstract {
protected:
unsigned long unique_id;
public:
SongAbstract() {
static unsigned long counter = 0;
unique_id = (counter++);
}
int play() const { return MusicPlayer::play(this->unique_id); }
void stop() const { MusicPlayer::stop(); }
unsigned long get_id() const { return unique_id; }
protected:
virtual void print_info(ostream& os) const = 0;
};
The question in the exam is as follows:
"From the code above it follows that an implementation of the class MusicPlayer is required.
Write a declaration for a class called AndroidMusicPlayer so that the program will run."
The official solution:
class AndroidMusicPlayer {
public:
static int play(unsigned long id);
static void stop();
};
I'm having trouble understanding what the constructor does and would very much appreciate it if someone could explain the following:
What is the purpose of defining the static data member inside the constructor?
Why are the methods in AndroidMusicPlayer declared as static? They access data member
"unique_id," which is not static.
What is the purpose of defining the static data member inside the constructor?
The counter variable inside the SongAbstract constructor is not a member of the class – it is a local variable. Being declared as static means that its value will be initialized (to zero) only once during the entire program run (the first time that constructor is called). That value is then incremented on each and every call, causing the actual member variable (unique_id) to be assigned a different value for each object constructed.
Why are the methods in AndroidMusicPlayer declared as static? They access data member "unique_id," which is not static.
Not quite! They are passed the value of the containing class member variable (well, one is); the confusion here is, perhaps, that the two functions have the same names as member functions of the containing class. The two functions of that SongAbstract class call the functions of the same name in the passed MusicPlayer class; those latter functions have to be static, because there is no instance of their class declared as a member of SongAbstract – hence why we pass the unique_id as an argument.
(The syntax MusicPlayer::stop() is here used to call a static class member; similar syntax can be used to call a non-static member, but only if the class is a base class of that from which it is being called.)
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.
From this reference:
(8.3.3/3) A pointer to member shall not point to a static member of a
class (9.4), a member with reference type, or "cv void."
Why a pointer cannot point to a static member of a class?
struct S {
static int f() { /*...*/ };
};
int main()
{
int (S::*s)() = &S::f; // why?
}
Why a pointer cannot point to a static member of a class?
Because for the purpose of membership it isn’t a member, merely for the purpose of scope. Apart from scope, static members are just like free functions, unattached to an instance of a class. You can use non-member function pointers:
int (*s)() = &S::f;
Whenever you do T::*, you're saying "this thing requires an instance of T to use." That statement does not hold for static functions, which are callable without any instances of the class.
You'd have to use a regular function pointer, like so:
int (*s)()=&S::f;
Like GMan said, static methods don't work on instances, so they don't receive the hidden this pointer. This effectively makes them have a different signature from instance methods with the same arguments.
Simplification of the code to express the concept:
class classA
{
public:
private:
int a;
seta(int x);
};
//local prototype
void somefunction();
int main()
{
classA object; //create an object of the class
somefunction(object);
return 0;
}
void somefunction(classA &object)
{
object.seta(5);
}
}
If I move seta() to the public section of the class there is no error and it executes.
However, if I move seta() to the private section, I get the following error:
error C2248:
'anonymous-namespace'::classA::seta' : cannot access
private member declared in class 'anonymous-namespace'::classA'
If the function is private and only this class is calling it, why is there an issue?
EDIT I am passing the object from main to the local function
The function that is calling seta() is not part of classA, so this is an error; that's the very definition of private. If you were to make somefunction() a member of classA, or declare it to be a friend of classA, then this would work.
The function somefunction() is not a member function of classA. It's a function with global scope and cannot access the private function seta(), just as main() cannot access the private function seta().
This has nothing to do with "local functions" (functions defined inside other functions). This is simply about public and private members.
If a member is private, then it can only be accessed by other members of that class, or by explicit friends of the class.
private means that only member functions and friends can access it. Both must be listed in the class declaration, but are not:
class classA
{
public:
private:
int a;
seta(int x);
};
Being in the same file doesn't make the function a part of the class -- only the class declaration is used to determine what has access.
Private members can only be accessed by it's members and it's friends. Also every member function in C++, should have a return type. With that said -
void main() // 1
{
classA object; //2
somefunction();
}
Return type of main should be int.
Scope of object is only in main and cannot be accessed in somefunction with out explicitly passing it to the function.
On your Edit:
You are passing object to somefunction(classA) by value. So, a copy of the object ( main scoped) is made to somefunction scoped object. Though they bear the same name, both are different.
void somefunction(classA object)
{ // ^^^^^^ Is a copy of the parameter passed.
object.seta(5); // This call isn't actually modifying the original parameter passed.
}// life time of argument,object, ends here.
You should pass it by reference instead if you wish to modify parameter passed itself.
Firstly, to answer your primary question:
If the function is private and only this class is calling it, why is
there an issue?
The issue is that private class members can only be invoked by other members of that class. The function somefunction() is not a member of classA and therefore does not have access to private member seta().
As an aside, you should also think carefully about what you're doing when passing object to somefunction() from main. You're passing object by value, so you're creating a copy of object scoped to somefunction() which will be destroyed as soon as somefunction() terminates. IS that what you want?
I suspect that you're intending to pass object to somefunction() from main by reference, in which case you need to declare somefunction() as
void somefunction(classA &object)
seta(int x) is a private member of ClassA, so only ClassA or a friend class of ClassA can access to this member. somefunction() is none of them.