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;
}
Related
So, I've been experimenting with static class fields (especially the constant ones), and got myself into.... this:
#include <iostream>
#include <conio.h>
class Test {
public:
Test() { std::cout << "Constructing (Default CTOR)\n"; }
Test(int f) { std::cout << "Constructing (Int arg CTOR)\n"; }
void method() const { std::cout << "Already constructed and being used\n"; }
};
class Stack {
public:
// static const Test what{ 5 }; // - "element of type "const Test" can not have an initializer inside of a class"
// const Test ok{ 5 }; // now it can (?)
static const Test what;
Stack() {
what.method();
}
// Stack() : what{5} {} // can't do that because "what" will be dependent on object creation (which is not how static class fields roll)
};
Stack obj;
const Test Stack::what{};
int main()
{
_getch();
return 0;
}
Output:
Apparently, static const Test what in Stack is being used before is has actually been created(?).
After that I ran another test:
#include <iostream>
#include <conio.h>
class Test {
public:
int data;
Test() { std::cout << "CONSTRUCTING (Default CTOR)\n"; } // notice, value-initialization of 'data' has been removed
Test(int f) : data{ f } { std::cout << "CONSTRUCTING (Int arg CTOR)\n"; }
void method() const { std::cout << "ALREADY CONSTRUCTED AND BEING USED :)\n" << data << std::endl; }
};
class Stack {
public:
static const Test what;
Stack() {
what.method();
}
};
Stack obj;
const Test Stack::what{ 5 };
int main()
{
obj.what.method();
_getch();
return 0;
}
In this code I was hoping to see some sort of error, but the output ended up looking like this:
I have some assumptions on what is happening here, but I'm not sure if they're correct. So, if they are, please correct me.
Here are my assumptions:
Basically, static variables are created at the very start of the program (and are value-initialized) and destoyed at the very end of the program (when you actually close your .exe).
In my examples I have a static constant variable what in the class Stack and I think it is being created at the beginning of my program value-initialized. That's why its data field is set 0 and we can use its methods. But I don't think that's correct because it would've output Constructing (Default CTOR) into the console. So I'm kinda stuck there...
I also can not understand why the commented lines in my first example are illegal. What rules of static/constant class fields do they break exactly?
If you have any idea to what is happening in my examples please explain it.
Thanks for your attention.
Static variables at namespace scope (i.e. not inside a function) are constructed in the order of their definitions in the source file. This ordering only applies between variables in the same source file, not between different source files.
So obj is always constructed before what. There are limited things that can be done with objects that have a constructor but before the constructor has been called; and invoking a member function is not one of them (C++14 [basic.life]/5.2). So the call what.method() in Stack's constructor causes undefined behaviour.
How do I meet below objective in C++ language.
My objective is to have an input source (a structure) defined in a constructor (or another method of same class) and access it in another method for processing.
For Eg:
#include "iostream"
class A
{
public:
struct source{ //input source
char* input;
unsigned int result;
};
A(); //constructor
~A(); //destructor
void process();
};
A::A()
{
//static local input source
static const source inp[2] = { {"input1", 2}, {"input2", 3} };
}
void A::process()
{
//The value of static structure "inp" initialized in constructor is to be
// read here.
// Say I want to print the "result"
std::cout << "input1 result" << inp[0].result; //should print 2
std::cout << "input2 result" << inp[1].result; //should print 3
}
Any alternate approach meeting above objective is most welcome.
Thanks in advance for the help.
It seems the best approach is to make the static constant variable a public member of the class, and then access it normally. See this post for more info:
C++ where to initialize static const
#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
}
Test.h
class Test
{
static int i;
};
Test.cpp
int Test::i = 1;
I know that normally we initialize a static member as above. And the static member is initialized before the function main runs.
My question is:
Is it possible to initialize the static member after the function main runs? Something like this:
int main()
{
// do something
// initialize the Test::i here
}
No, it isn't possible to initialize it, but there should be no reason why you can't just call a static setter function that assigns a value to i in run-time. This is the best method.
Or you alternatively, you could make it so that the constructor always initializes the variable:
#include <iostream>
class Test
{
private:
static int i;
public:
Test()
{
i=2;
}
void print_i (void)
{
std::cout << i << std::endl;
}
};
int Test::i = 1;
int main()
{
Test test;
test.print_i(); // will print 2
}
I'm going to assume that you really mean initialization, so that assignment after main has started is out. This will not make a difference for basic types like int or double, but may make one for complex data types.
The answer is: no but yes (sort of). It is not possible to delay the initialisation of a static data member until after main started, but you can use a static member function with a function-local static object to simulate the effect. This object will be initialized after the function is first called. In code:
#include <iostream>
struct A {
A() {
std::cout << "A::A()\n";
}
void do_something() {
std::cout << "A::do_something()\n";
}
};
struct B {
static A &a() {
static A instance;
return instance;
}
};
int main() {
std::cout << "main start\n";
B::a().do_something();
B::a().do_something();
std::cout << "main end\n";
}
This will print
main start
A::A()
A::do_something()
A::do_something()
main end
You would then use B::a() where you'd have used B::a before. You will have to make sure that the function is not called before main is started.
The first mistake you have is that the variable 'i' is private for the class, so you cannot access it outside the class. There are two ways to fix this. The first is to make it public(not preffered) and the second to make setter and getter methods.
About the question the answer is yes, you can. Use the setter method I mentioned above.
These are the two methods:
//…
public:
static int get_i() {
return i;
}
static void set_i(int val) {
i = val;
}
//…
You can call the method like that:
Test::set_i(10);
Note: do not forget to include the keyword public before the methods so you can access them outside the class.
You're confusing the word static and the word const.
You have to initialize a const when you declare it;
You don't have to initialize a static when you declare it, but you can change it anywhere anytime, given you can access it. (which is not the case here, your i is private.)
About thoses statements, let's look at the C++ standard (3.6.2) :
Variables with static storage duration or thread storage duration
shall be zero-initialized before any other initialization takes place.
Technically, yes, your static data is always zero-initialized even if you explicitely initialize 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.)