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.)
Related
What are the major differences between the static class member variable and the static variable ?
Both static class members and static varibles are accessed from member functions of any class. What are the specific uses of static class members and static varibles?
The only reason is code cleanliness. You cannot restrict access to a global static variable like
static int globalValue=5;
it is (at least) visible in the source file you defined it.
With a class static, you can give a user of your class hints, how you wish to access it or be accessed. It is only visible within the class scope:
class myGlobalContainer
{
public:
static int myInt;
protected:
static float myFloat;
private:
static bool myBool;
};
the access of myInt is done by:
int x=myGlobalContainer::myInt;
the public modifier gives the user the hint that you see this value as part of the myGlobalContainer and wish him to use it. You do not polute the global namespace like you do with the globalValue.
The modifier protected and private shows that you do not wish that an "outsider" access those values.
protected and private static attributes are mostly used to share information between the instances of a class, for e.g. a instance counter:
class myGlobalContainer
{
public:
myGlobalContainer()
{
if(counter==0)
DoSomeSpecialGlobalInit();
counter++;
}
~myGlobalContainer()
{
counter--;
if(counter==0)
DoSomeSpecialGlobalUnInit();
}
private:
static int counter=0;
};
public static attributes are often seen with const. They mostly give a user a shortcut. For e.g.:
COLOR white=COLOR::WHITE;
instead of:
COLOR white=COLOR::FromAGBR(255,255,255,255);
Add least:
If you should use statics or not is a complete other discussion.
Both static class members and static varibles are accessed from member
functions of any class.
That is not true:
class A {
private:
static int x;
};
int A::x = 5;
class B {
static int y;
public:
void do_something()
{
std::cout << A::x; // Can't access A::x because it's private
}
};
int B::y = 10;
Although, if we did this:
static int J = 9;
class A {
private:
static int x;
};
int A::x = 5;
class B {
static int y;
public:
void do_something()
{
std::cout << J; // Yes, J is global.
}
};
int B::y = 10;
Static member variables can access the private section of it's class opposed to a normal static variable.
Static member variables may not be defined inside the class body, unless it's const static or constexpr static.
Static member variables may be used as default arguments for the member functions in their class. Opposed to normal static variables, unless they are global.
Uses: if you want a variable to be alive until the end of your program in both cases but static member variables have access to the private section of that class.
We can define class members static using static keyword. When we declare a member of a class as static it means no matter how many objects of the class are created, there is only one copy of the static member.
If you declare a static member public then you can access it without member functions as well.. Static has nothing to do with the scope of variable.. It specifies the storage duration only..
A static member is shared by all objects of the class. All static data is initialized to zero when the first object is created, if no other initialization is present.
My list of differences:
You can make static class member protected or private.
You can't make static class member global.
Can't think of anything else.
Static class members are used to share data between different instances of a class. The storage for these members is allocated only once and it is only this instance of the static member that will be available for all objects of the class.
Static variables inside a function are variables that retain its value through function calls.
A classic but simple example of this is a int type static counter in a function where you want to keep track of the number of times this function was called. Since this retains its value through calls, you can increment it inside the function every time it is called.
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.
Suppose we have a class as
class Egg
{
static Egg e;
int i;
Egg(int ii):i(ii) {}
Egg(const Egg &); //Prevents copy-constructor to be called
public:
static Egg* instance() {return &e}
};
Egg Egg::e(47);
This code guarantees that we cannot create any object, but could use only the static object. But how could we declare static object of the same class in the class.
And also one thing more since e is a static object, and static objects can call only static member functions, so how could the constructor been called here for static object e, also its constructors are private.
But how could we declare static object of the same class in the class.
A static member variable is not stored inside each object of a class. So if you declare a static member variable inside a class or as a namespace level object after you defined the class, differs only in respect to access (Class::var and var) and access to protected and private members.
And also one thing more since e is a static object, and static objects can call only static member functions
I think you are mixing static functions and static objects. Inside a static function you can call only static functions (unless you are calling them on an object).
so how could the constructor been called here for static object e
Like for every other object a constructor has to be called for static objects, too.
also its constructors are private
Access Control is checked on class level in C++. So since the static object is inside the class, it can access private members.
Unlike in some other languages, the following is legal in C++, since the access to a private member is from inside the class - even if on another object (other in this case):
class Test {
private:
int i;
public:
Test(const Test &other)
: i(other.i)
{}
};
But how could we declare static object of the same class in the class.
Normally you'd need a forward reference, but since Egg e is static, it's actually defined outside of the class definition. If e was not static, you'd get an error (something like "field Egg e has incomplete type").
And also one thing more since e is a static object, and static objects can call only static member functions, so how could the constructor been called here for static object e.
This is not quite true. A static member function within a class can only access static member data. static Egg e is an instance of Egg, so it can access all the members and data a regular Egg can.
also its constructors are private.
Any private member can be used from within a class. Since static Egg e is declared as a member of Egg, it can use the private constructor. The definition of e is outside the class since it's static, but it is still a class member.
And lastly your code doesn't compile because you left out a semicolon here:
static Egg* instance() {return &e;}
I see some usage of internal struct in c++ function.
There is a common interface IBase. Here is the draft code.
class IBase
{
virtual Method()=0;
}
vector<IBase*> baseList;
Then a function defined an internal class based on that IBase, and then push the internal class object into the baseList.
void func()
{
struct Object : public IBase
{
virtual Method()
{
// Method of Object in func
}
}
IBase* base = new Object();
baseList->push(base);
}
It seems a strange usage, but a nice implementation of message/event creation pattern.
Other threads maybe use this baseList to handle the incoming event.
What's the scope of internal struct of "struct Object"? It's very interesting. Is there some documents talking about this?
What's the scope of internal struct of "struct Object"?
The scope of the local classes is the function in which they're defined.But that isn't interesting in itself.
What makes local classes interesting is that if they implement some interface (like your code does), then you can create instances of it (using new) and return them (for example, as std::vector<IBase*>), thereby making the implementation accessible through the base class pointer even outside the function.
Some other facts about local classes:
They cannot define static member variables.
They cannot access nonstatic "automatic" local variables of the enclosing function. But they can access the static variables.
They can be used in template functions.
If they are defined inside a template function, then they can use the template parameters of the enclosing function.
Local classes are final, that means users outside the function cannot derive from local class to function. Without local classes, you'd have to add an unnamed namespace in separate translation unit.
Local classes are used to create trampoline functions usually known as thunks.
EDIT
Some references from the Standard (2003)
9.8 Local class declarations [class.local]
\1. A class can be defined within a function definition; such a class is
called a local class. The name of a
local class is local to its enclosing
scope. The local class is in the scope
of the enclosing scope, and has the
same access to names outside the
function as does the enclosing
function. Declarations in a local
class can use only type names, static
variables, extern variables and
functions, and enumerators from the
enclosing scope.
[Example:
int x;
void f()
{
static int s ;
int x;
extern int g();
struct local {
int g() { return x; } // error: x is auto
int h() { return s; } // OK
int k() { return ::x; } // OK
int l() { return g(); } // OK
};
// ...
}
local* p = 0; // error: local not in scope
—end example]
\2. An enclosing function has no special access to members of the local
class; it obeys the usual access rules
(clause 11). Member functions of a
local class shall be defined within
their class definition, if they are
defined at all.
\3. If class X is a local class a nested class Y may be declared in
class X and later defined in the
definition of class X or be later
defined in the same scope as the
definition of class X. A class nested
within a local class is a local class.
\4. A local class shall not have static data members.
\4. A local class shall not have static data members.
BUT you can do this, inside of a local class
int GetCount()
{
class _local
{
public:
static int Count(int count = std::numeric_limits<int>::max())
{
static int count_ = 0;
if (count != std::numeric_limits<int>::max()) count_ = count;
return count_;
}
static float Operation(float a, float b)
{
_local::Count(_local::Count() + 1);
return a;
}
};
_local::Count(0);
CALLBACK( _local::Operation);
return _local::Count();
}
_local::Count can be used to read and write the otherwise static variable
-aydin
This is normal C++. The scope of struct Object is only the function func. However, you can still use objects of this type without knowing which concrete type they are, since they inherit from IBase. This is used to encapsulate implementation.
A very interesting use of a local class is presented by Jason Turner in his CppCon talk focused on programming of Commodore 64 game in C++17. He shows how to use the RAII principle on the function level.
He basically establishes invariants in the constructor of a local class in a function returning an instance of this class. The invariants duration is thusly controlled by the lifetime of the returned object. It is quite similar to what RAII wrappers like std::lock do, just slightly different.
You can see the appropriate part here, but I love his performance and recommend to see it all the way through.
I have one question about static and non-static function and variable.
1) non-static function access static variable.
It's OK!
class Bar
{
public:
static int i;
void nonStaticFunction() {
Bar::i = 10;
}
};
int Bar::i=0;
2) non-static function access non-static variable
Definitely OK!
3) static function access static variable&funciton
Definitely OK!
4) static function access non-static function
It's OK
class Bar
{
public:
static void staticFunction( const Bar & bar)
{
bar.memberFunction();
}
void memberFunction() const
{
}
}
5) static function access non-static variable
It's OK or not OK? I am puzzled about this!
How about this example
class Bar
{
public:
static void staticFunction( Bar & bar)
{
bar.memberFunction();
}
void memberFunction()
{
i = 0;
}
int i;
};
static function access non-static
variable
It's OK or not OK? I am puzzled about
this!
When called, a static function isn't bound to an instance of the class. Class instances (objects) are going to be the entities that hold the "non-static" variables. Therefore, from the static function, you won't be able to access them without actually being passed or storing elsewhere a specific instance to operate on.
So yes, the code in your last example is valid, because you are passed in an instance. However, you could not do:
static void staticFunction()
{
// error, this function is static, and is therefore
// not bound to a specific instance when called
i = 5;
}
Static means this is independent of a particular instance of the class. Static methods don't have access to the this pointer. That is the reason you need to call them using the class name.
When you call the Static method, you might not even have any instance of the class defined.
non-static means implies an instance, and could be different with different instances.
So, basically, it does not make sense to access non-static members from static methods.
For this, you need to understand what is static.
Static data members exist once for the entire class, as opposed to non-static data members, which exist individually in each instance of a class. They will have a class scope and does not bound to an instance of the class.
To access static member of the class, we use the format as below
::
if you have created 10 objects of a class.
Assume, you were able to access the non-static variable in the static member of the class, When the static function is called, which object's member it needs to change?
It's not ok. Static functions are accessible without having an instance of a class and thus can't access information that you would need an instance to determine.
For example, you don't need a car to know how many wheels it has, blueprints for a general car would suffice (that could be static information) but you can't tell what color the car is unless you're referring to a specific car (that information needs a specific instance of an object.)