class test {
public:
static int n;
test () { n++; };
~test () { n--; };
};
int test::n=0; //<----what is this step called? how can a class be declared as an integer?
int main () {
test a;
test b[5]; // I'm not sure what is going on here..is it an array?
test * c = new test;
cout << a.n << endl;
delete c;
cout << test::n << endl;
}
secondly, the output is 7,6 I'm not understanding how did it get 7, from where?
From the statement-
int test::n=0;
'::' is called scope resolution operator. This operator is used here to initialize the static field n, not the class
Static data members are declared in class. They are defined outside the class.
Thus in the class definition
class test {
public:
static int n;
test () { n++; };
~test () { n--; };
};
record
static int n;
only declares n. You need to define it that is to allocate memory for it.
And this
int test::n=0;
is its definition. test::n is a qualified name of the variable that denotes that n belongs to class test.
According to the class definition when an object of the class is constructed this static variable is increased
test () { n++; };
And when an object is destructed this static variable is decreased
~test () { n--; };
In fact this static variable plays a role of counting alive objects of the class.
Thus in main you defined object of the class with name a
test a;
Each time an object is defined the constructor of the class is called. Consequently n was increased and becomes equal to 1.
Adter defining array of 5 objects
test b[5];
n becomes equal to 6.
After dynamically allocating one more object
test * c = new test;
n becomes equal to 7.
After its explicit deleting
delete c;
n again becomes equal to 6 because called destructor decreased n.
Related
The following is a class template that implements a stack using an array:
#include <iostream>
using namespace std;
template <typename T>
class stack {
public:
stack (int priv_size) {
T a[priv_size];
top = 0;
}
stack (const stack &s) {
T b[priv_size];
for (top=0; top<s.priv_size; top++) {
b[top] = s.a[top];
}
top++;
}
~stack () {}
const stack& operator = (const stack &s) {
T b[s.priv_size];
for (top=0; top<s.priv_size; top++) {
b[top] = s.a[top];
}
top++;
}
bool empty () {
return top == 0;
}
void push (const T &x) {
a[top++] = x;
}
T pop () {
T c = a[--top];
return c;
}
int size () {
return priv_size;
}
friend ostream& operator << (ostream &out, const stack &s) {
int i;
out << "[";
for (i=0; i<s.top-1; i++) {
out << s.a[i] << ", ";
}
if (i == s.top-1) out << s.a[s.top-1];
out << "]";
return out;
}
private:
int priv_size;
int top;
T a[];
};
int main () {
stack<int> s(10);
cout << "stack s is empty: " << s << endl;
s.push(42);
s.push(17);
cout << "stack s has 2 elements: " << s << endl;
cout << "Removing " << s.pop() << " from the stack..." << endl;
return 0;
}
However as i was trying out the different methods of the class in main I realized that although priv_size is initialized to the value of 10 here: stack<int> s(10); it loses its value right after the constuctor is called.
When i tried debugging in my IDE i realized that once the constructor stack (int priv_size) is called it created another variable priv_size that is initialized to the value of 10 instead of using the priv_size member of the class. The previous can also be seen here:
class member priv_size memory address (image)
and here:
unwanted variable priv_size memory address (image)
where the two variables are stored in different memory slots.
Why are the two variables different and why is the one in the second image created in the first place?
I have also tried implementing the class methods outside of the class, like this:
stack<T>::stack (int priv_size) {
T a[priv_size];
top = 0;
}
but i get these two error messages:
Member declaration not found
Type 'T' could not be resolved
What is going on here?
Thanks in advance.
PS: I am aware there are a couple very similar questions posted already, but the answers to those do not seem to fit my problem as my issue seems to be in the class itself and not in main or any other function.
Here are two links to some similar questions:
C++ Class members lose values assigned in a member function
Losing a data member of a base class after the constructor is called
stack (int priv_size) {
T a[priv_size];
top = 0;
}
Problem 1: Your constructor doesn't initialise the member a. It creates a local array.
Problem 2: The size of the array is not a compile time constant. The program is ill-formed.
Problem 3: You don't initialise the priv_size member either.
private:
int priv_size;
int top;
T a[];
Problem 4: You didn't specify size of the array member a. The program is ill-formed.
although priv_size is initialized to the value of 10 here: stack s(10); it loses its value right after the constuctor is called.
Your assumption is wrong. The constructor doesn't set the value of priv_size member, so no value was lost.
where the two variables are stored in different memory slots.
As far as I can tell, one variable is the parameter of the constructor and the other is the member variable that you didn't initialise.
Type 'T' could not be resolved
What is going on here?
To define a template, you need to use the keyword template and specify the template parameters. Like this for example:
template <typename T>
stack<T>::stack (int priv_size) {
Why are the two variables different and why is the one in the second image created in the first place?
Because you declared two different variables.
Its the same issue as in :
struct foo {
int x;
foo(int a) {
int x = a;
}
};
foos constructor declares a local variable named x which shadows the member x and the member x is not initialized. Same with an array:
struct bar {
int a[5];
bar() {
int a[5];
}
};
The member a and the a in the constructor are two distinct arrays.
This is only answering your question, but there are more problems in your code. When you need an array whose size is only known at runtime you should use std::vector.
There are multiple issues with your code. For instance, T a[priv_size]; requires that priv_size is a compile-time constant. And in stack (const stack &s) {T b[priv_size];, the local variable b goes out of scope when the copy ctor ends, while the member a remains uninitialized.
#include<iostream>
using namespace std;
class Test
{
public:
static int Retr(); // Static member function
//~Test(); // Test destructor
Test(); // Default constructor
private:
static int count; // Static member variable
int i;
};
int Test::count = 0; // Initialization
int main()
{
Test obj;
cout << Test::Retr() << endl;
// The result should be 1 but prints two
return 0;
}
Test::Test() : i(1) { Retr(); }
int Test::Retr()
{
return ++count;
}
/*
Test::~Test()
{
count--;
}
*/
I'm practising about usage of static member function and variable. I have a static member function that counts and returns how many objects are constructed. It should show 1 for this example but it shows 2. I don't understand why it happens. However, the destructor decreases the counter end of scope for every constructed objects. Doesn't it? So, the result using with destructor should be 0. But, I can't get the expected results. Could someone explain?
Edited what about not working of destructor ? Solved
#include<iostream>
using namespace std;
class Test
{
public:
static int Retr(); // Static member function
~Test(); // Test destructor
Test(); // Default constructor
private:
static int count; // Static member variable
int i;
};
int Test::count = 0; // Initialization
int main()
{
Test obj[2];
cout << Test::Retr() << endl;
// The result should be 0 because of destructor but prints 2
return 0;
}
Test::Test() : i(1) { ++count; }
int Test::Retr()
{
return count;
}
Test::~Test()
{
--count;
cout << Test::Retr() << endl;
}
Test::Test() : i(1) { Retr(); }
When you have created an object, It also calls retr() function. Thats increments count; And again you call retr() to show..
Your destructor is working.Call Test::Retr() to check count after destruction.
Test::~Test()
{
--count;
cout << Test::Retr() << endl;
}
First things first, you need to understand what is a static member function.
Static members of a class are not associated with the objects of the class: they are independent objects with static storage duration or regular functions defined in namespace scope, only once in the program.
So your entire program will only have one instance of count (Which is initialized to 0)
Let us look at the code in the main function, you're creating an object of the class Test. Hence the constructor gets called, which inturn calls the static int Retr() function. Hence count is now 1. Now,
cout << Test::Retr() << endl;
Calls Retr() again, hence it increments count and returns the value. Hence 2 is returned.
As far as the destructor is concerned, it is not called before the cout. It will be called only when obj goes out of scope, which will happen only when the main function is completed.
When you are creating
Test obj;
It calls the constructor and increments 1
and again you are calling
Test::retr()
It also increments 1.
If you want to check the behavior of your class you can add additional function as
void testFunction(){
Test obj[2];
std::cout << Test::Retr() << std::endl; // count became 3
}
int main(){
testFunction();
// Obj destructed here count became 1
std::cout << Test::Retr() << std::endl;
// It will again increment and count will be 2
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
file scope and static floats
What are static variables?
Here is a code from a book.
class X
{
int i;
public:
X(int ii = 0) : i(ii) {cout<<i<<endl;} // Default
~X() { cout << "X::~X()" << endl; }
};
void f()
{
static X x1(47);
static X x2; // Default constructor required
}
int main()
{
f();
return 0;
}
My question is why would I like to declare an object as static like in function f()? What would happen if I did not declare x1 and x2 as static?
For this code it makes no difference to the observable behavior of the program.
Change main to call f twice instead of only once, and observe the difference -- if the variables are static then only one pair of X objects is ever created (the first time f is called), whereas if they're not static then one pair of objects is created per call.
Alternatively, change main to print something after calling f. Then observe that with static, the X objects are destroyed after main prints (the static objects live until the end of the program), whereas without static the objects are destroyed before main prints (automatic objects only live until exit from their scope, in this case the function f).
The first time the function f() is hit the statics will be initialized (lazy loading). Had they not been declared static then they would be local variables and recreated every time you called function f().
All calls to f() will result in using the same x1 and x2.
The difference between
int f()
{
int i = 0;
++i;
return i;
}
int f2()
{
static int i = 0;
++i;
return i;
}
int main()
{
for (int i = 0; i < 10; ++i) { cout << f1() << ' ' << f2() << endl; }
}
Is that f1 will always make a new local variable i and set it to zero then increment it, while f2 will create a static local variable i and initialize it to zero once and then each call it increments it from the previous call value.
Here is some code to test what does a static object within a function mean:
#include <iostream>
using namespace std;
class A {
public:
void increase() {
static int b = 0;
b++;
cout << "A::increase: " << b << endl;
}
};
int main() {
A a;
a.increase();
a.increase();
a.increase();
return 0;
}
And the output is:
A::increase: 1
A::increase: 2
A::increase: 3
Notice the value of b is kept between function calls? Here is the example on ideone so that you can play with it.
Can there be a member variable in a class which is not static but which needs to be defined
(as a static variable is defined for reserving memory)? If so, could I have an example? If not, then why are static members the only definable members?
BJARNE said if you want to use a member as an object ,you must define it.
But my program is showing error when i explicitly define a member variable:
class test{
int i;
int j;
//...
};
int test::i; // error: i is not static member.
In your example, declaring i and j in the class also defines them.
See this example:
#include <iostream>
class Foo
{
public:
int a; // Declares and defines a member variable
static int b; // Declare (only) a static member variable
};
int Foo::b; // Define the static member variable
You can now access a by declaring an object of type Foo, like this:
Foo my_foo;
my_foo.a = 10;
std::cout << "a = " << my_foo.a << '\n';
It's a little different for b: Because it is static it the same for all instance of Foo:
Foo my_first_foo;
Foo my_second_foo;
Foo::b = 10;
std::cout << "First b = " << my_first_foo.b << '\n';
std::cout << "Second b = " << my_second_foo.b << '\n';
std::cout << "Foo::b = " << Foo::b << '\n';
For the above all will print that b is 10.
in that case, you would use the initialization list of test's constructor to define the initial values for an instance like so:
class test {
int i;
int j;
//...
public:
test() : i(-12), j(4) {}
};
That definition reserves space for one integer, but there'll really be a separate integer for every instance of the class that you create. There could be a million of them, if your program creates that many instances of test.
Space for a non-static member is allocated at runtime each time an instance of the class is created. It's initialized by the class's constructor. For example, if you wanted the integer test::i to be initialized to the number 42 in each instance, you'd write the constructor like this:
test::test(): i(42) {
}
Then if you do
test foo;
test bar;
you get two objects, each of which contains an integer with the value 42. (The values can change after that, of course.)
This question was asked to me in an interview:
What is a static constructor?
Does it exist in C++? If yes, please explain it with an example.
C++ doesn’t have static constructors but you can emulate them using a static instance of a nested class.
class has_static_constructor {
friend class constructor;
struct constructor {
constructor() { /* do some constructing here … */ }
};
static constructor cons;
};
// C++ needs to define static members externally.
has_static_constructor::constructor has_static_constructor::cons;
In C++, there is no static constructor. In C# (and probably in Java too), you can define static constructor which is called automatically by the runtime so as to initialize static members.
For further question and interest you can read this topic:
What is the rationale for not having static constructor in C++?
Since we do not technically have static constructors in C++, you have to decide whether it is worth it to do something tricky to force the issue (e.g. using a static instance of a nested class), or to just slightly restructure your code to call a static initializer early in your program's life.
#include <iostream> // cout, endl
class Foo {
public:
static int s_count;
// Constructor definition
Foo (int l, int w, int h)
{
cout <<"Foo ctor called." << endl;
length = l;
width = w;
height = h;
// Increase every time object is created
s_count++;
}
int vol ()
{
return length * width * height;
}
static void initCount()
{
s_count = 0;
}
static int getCount()
{
return s_count;
}
private:
double length; // Length of a box
double width; // Width of a box
double height; // Height of a box
};
// Initialize static member of class Foo
int Foo::s_count; // Initializing here is non-deterministic
int main(void) {
Foo::initCount(); // Initializing here is deterministic
// Print total number of objects before creating object.
cout << "Inital Count: " << Foo::getCount() << endl;
Foo Foo1(3, 1, 1); // Declare box1
Foo Foo2(8, 6, 2); // Declare box2
// Print total number of objects after creating object.
cout << "Final Count: " << Foo::getCount() << endl;
return 0;
}
Output:
$ static_init_test
Inital Count: 0
Foo ctor called.
Foo ctor called.
Final Count: 2
I like this approach better; as a silver lining, it takes the non- out of non-deterministic initialization.
There is one gotcha though -- this technique is insufficient if you are trying to initialize static const variables. For static const variables, you will have to make them private to the class and provide getters for outsiders to read them.
Note: I updated this code -- it compiles and runs successfully with no warnings via:
g++ static_init_test.cpp -std=c++11 -o static_init_test
Static constructors exist in C# and Java.
They are used to initialize static members of a class.
The runtime executes them before the class is first used.
There is no such thing in C++. Constructors and destrcutors typically used to create or destruct instance of object. It's meaningless to call them without corresponding object instance. You can emulate them using a singleton pattern.
A static constructor is used to initialize static data of a class. C++ doesn't have static constructor. But a static constructor can be emulated by using a friend class or nested class as below.
class ClassStatic{
private:
static char *str;
public:
char* get_str() { return str; }
void set_str(char *s) { str = s; }
// A nested class, which used as static constructor
static class ClassInit{
public:
ClassInit(int size){
// Static constructor definition
str = new char[size];
str = "How are you?";
}
} initializer;
};
// Static variable creation
char* ClassStatic::str;
// Static constructor call
ClassStatic::ClassInit ClassStatic::initializer(20);
int main() {
ClassStatic a;
ClassStatic b;
std::cout << "String in a: " << a.get_str() << std::endl;
std::cout << "String in b: " << b.get_str() << std::endl;
a.set_str("I am fine");
std::cout << "String in a: " << a.get_str() << std::endl;
std::cout << "String in b: " << b.get_str() << std::endl;
std::cin.ignore();
}
Output:
String in a: How are you?
String in b: How are you?
String in a: I am fine
String in b: I am fine
May be they mean this:
class Cat
{
private:
Cat();
public:
static Cat getCat() {return Cat(); }
}
In C++, there is no such thing as a static constructor.
I think static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced. In++, we dont have anything called static constructor but you can mimic the functionality of the static constructor. Take a look at this C# static constructor:
public class Bus {
// Static variable used by all Bus instances.
// Represents the time the first bus of the day starts its route.
protected static readonly DateTime globalStartTime;
// Property for the number of each bus.
protected int RouteNumber { get; set; }
// Static constructor to initialize the static variable.
// It is invoked before the first instance constructor is run.
static Bus()
{
globalStartTime = DateTime.Now;
// The following statement produces the first line of output,
// and the line occurs only once.
Console.WriteLine("Static constructor sets global start time to {0}",
globalStartTime.ToLongTimeString());
}
// Instance constructor.
public Bus(int routeNum)
{
RouteNumber = routeNum;
Console.WriteLine("Bus #{0} is created.", RouteNumber);
}
// Instance method.
public void Drive()
{
TimeSpan elapsedTime = DateTime.Now - globalStartTime;
// For demonstration purposes we treat milliseconds as minutes to simulate
// actual bus times. Do not do this in your actual bus schedule program!
Console.WriteLine("{0} is starting its route {1:N2} minutes after global start time {2}.",
this.RouteNumber,
elapsedTime.Milliseconds,
globalStartTime.ToShortTimeString());
} }
class TestBus {
static void Main()
{
// The creation of this instance activates the static constructor.
Bus bus1 = new Bus(71);
// Create a second bus.
Bus bus2 = new Bus(72);
// Send bus1 on its way.
bus1.Drive();
// Wait for bus2 to warm up.
System.Threading.Thread.Sleep(25);
// Send bus2 on its way.
bus2.Drive();
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
} } /* Sample output:
Static constructor sets global start time to 3:57:08 PM.
Bus #71 is created.
Bus #72 is created.
71 is starting its route 6.00 minutes after global start time 3:57 PM.
72 is starting its route 31.00 minutes after global start time 3:57 PM.
*/
Here is the simplest static constructor in c++17:
#include <iostream>
class h {
public:
static inline int i;
private:
struct constructor {
constructor() {
i=3;
}
};
static inline constructor cons;
};
int main() {
std::cout << h::i;
}
See my answer to a similar question. C#'s static-constructor metaphor can be done in C++.
In C++, if someone says "static constructor", they are generally referring to "static initialization" (and destruction). It's not uncommon to use this terminology.
Other way to emulate static constructor behaviour is to use instance variable with private constructor and static factory method.
Cat* Cat::give_birth() {
static Cat *myone = NULL;
if (myone == NULL) {
myone = new Cat();
}
return myone;
}