I have following code:
#include <iostream>
using namespace std;
class Base
{
private:
int i;
char ch;
public:
void showdata()
{
cout<<"Int:"<<i<<endl;
cout<<"Char:"<<ch<<endl;
}
//int pub_data ;
} ;
int main()
{
Base ob;
ob.showdata() ;
//cout<<"Public Data:"<<ob.pub_data<<endl;
return 0;
}
This program compiles and runs fine. The output shows that i is initialized with 0 and ch is initialized with '\0'.
If you notice i have commented out 2 statements in this program. First the declaration of public data pub_data and second the line inside main printing this public data.
Now here the problem is, if i uncomment these two lines, the data members of class i.e. i, ch, pub_data do not seem to be initialized and when printed, they display junk values.
So my question is what difference public data makes here?
I'm using g++ 3.4.6
Neither int's nor char's are automatically initialized to 0. The fact that it happened is just luck.
You need to add a constructor that does the initialization:
Base() : i(0), ch(0) {}
None. You're just getting "lucky". Fundamental types remain uninitialized, so your i and ch, as the program stands, could very well not always be 0.
It just so happens adding that public member "messes it up". To correct your class, initialize the members in the initialization list of the constructor:
class Base
{
private:
int i;
char ch;
public:
Base(void) :
i(0), ch(0) //, pub_data(0)
{}
void showdata()
{
cout<<"Int:"<<i<<endl;
cout<<"Char:"<<ch<<endl;
}
//int pub_data ;
} ;
Now when a Base gets constructed i, ch, and (when uncommented) pub_data will be properly initialized to meaningful values.
As opposed to Java or C#, where memory allocated for a newly created objects ALWAYS set to zero, this NOT happends in C++. There are several rules that describe when object initialization is guaranteed to take place and when it isn't.
Consider folowing example:
class Base
{
private:
int i;
char ch;
std::string str;
public:
Base()
: i(0) //built-in fields remains unitialized. We should initialize it manually
, ch('\0') //another built-in field
//, str() //this call is redundant due automatic default constructors calls for all user-defined types
{}
void showdata()
{
cout<<"Int:"<<i<<endl; //valid only after manual initialization
cout<<"Char:"<<ch<<endl; //valid only after manual initialization
cout<<"String:"<<str<<endl; //always valid
}
//int pub_data ;
} ;
You should remember, that ALL buit-in fields you should initialized manually in class constructor.
P.S. The fact, that in the first case your code works - is pure accident.
What has been answered already is correct, but to make sure your values are zero-initialized you can also simply declare your object as
Base ob(); // notice the parentheses here
or
Base ob{}; // this compiles only on c++11
For more details, check out this insightful answer:
https://stackoverflow.com/a/620402/3073460
Related
I am a newbie in C++. Here in my case I have created two classes, class One and class Two. _x is declared as a private member variable of class One. So here I am trying to learn different methods to access this private variable(_x) from any other class(Here in this case it is class Two). This is my scenario basically. So one method I tried is ,making class Two as a friend class of class One and for accessing this variable, I have used directValOfOne function to print the value of this variable and another one I tried was passing the address of the class One instance in another member function (getDataTwo) of class Two. Everything works well until here.
As you can see, I have initialized the _x using a parameterized constructor and printing this variable gives me the value as 10 using both the methods. Again I modified this variable using a
setter function (setDataOne) to 220 and when I print it using the getDataTwo function it prints the value as 220. But when I tried to print the value using directValOfOne, it still showing the old initialized value (10) which I am really confused. I have printed the address of class One object in this directValOfOne funtion and it shows same. If so then why the new value(220) is not updated here.
Source code is placed below.
#include <iostream>
using namespace std;
class One{
int _x;
public:
One(int a):_x{a} {}
//setters and getters
void setDataOne(int a) { _x = a; }
int getDataOne() const { return _x; }
//print values
void printOne() { cout<<"_x - "<<_x<<endl; }
friend class Two;
};
class Two{
One _a;
int id_one = 0;
public:
Two(One a):_a{a} {}
//setters and getters
void setDataTwo(int a) { }
int getDataTwo(One *obj) {
id_one = obj->getDataOne();
return id_one;
}
void printTwo() { printf("id_one = %d\n",id_one); }
void directValOfOne() {
printf("address = %p\n",&_a);
printf("_a._x = %d\n",_a._x);
}
};
int main(){
One one(10);
Two two(one);
one.printOne();
two.getDataTwo(&one);
two.printTwo();
two.directValOfOne();
printf(" *********** \n");
one.setDataOne(222);
one.printOne();
two.getDataTwo(&one);
two.printTwo();
two.directValOfOne();
return 0;
}
and the console output is,
_x - 10
id_one = 10
address = 006dfee4
_a._x = 10
***********
_x - 222
id_one = 222
address = 006dfee4
_a._x = 10
As you can see the _a._x still prints the value 10. But actually the _x is updated to new value 220. Sorry if I explained it so detail. Just to give you an overview I detailed like this.
So my que is ,
Why it is not showing the updated value since the addresses are same?
Am I missing any important concept here ? If so please guide me to understand this problem.
The problem in your code is that you pass to Two an instance of class One by value. This means that Two stores a copy of the instance of One you pass to it. When you change the value of _x in one it does not affect the value of _x in _a (inside two).
In order for your code to work you need to pass a reference to One in Two's constructor and store this reference. Now every change to one will also affect _a.
Modified code:
class Two{
One& _a;
int id_one = 0;
public:
Two(One& a):_a(a) {}
// ...
Regarding the address issue, the address of _a will stay the same since there's no reason for it to change once initialized. If you'll print the address of one in your current code (before the suggested modifications) it should be in a different address than _a (since _a is a copy that's located somewhere else).
In the modified version of the code you should see the same address since it's the same object.
I want to use a two dimensional array of constant size as a class member in C++. I have problems initializing it in the constructor though.
Here are my non-working tries:
1.)
class A {
public:
int a[2][2];
A();
};
A::A() {
a = {{1,2},{2,4}};
}
yields: error: assigning to an array from an initializer list
2.)
class A {
public:
int a[2][2];
A();
};
A::A() {
int b[2][2] = {{1,2},{2,4}};
a = b;
}
yields: invalid array assignment
3.)
class A {
public:
int **a;
A();
};
A::A() {
int b[2][2] = {{1,2},{2,4}};
a = b;
}
yields: cannot convert ‘int [2][2]’ to ‘int**’ in assignment
I come from C background. I know that I could use std::vector and I am aware of the disadvantages this approach has but since this is an exercise for me I would like to know how to get it working with plain arrays. I should add that I want to work on this array later on. I want to change the stored values but not the size. Maybe that matters as well (I figured a const at the right place could help somehow?).
If you have C++11, you can use this syntax in the constructor definition:
A() : a{{1,2}, {3, 4}} {}
If you don't have C++11, you will need to stick to the wicked old ways:
A() {
a[0][0] = 1;
// etc
}
The first example also uses the constructor init-list, which should always be used to initialize members instead of intializing them in the constructor body.
various multidimensional array in constructor by example:
// int array1[1];
A() : array1{0} {}
// int array2[2][2];
A() : array2{{0}} {}
// int array3[3][3][3];
A() : array3{{{0}}} {}
Try this, it works for bidimensional array (in standard C++):
class A {
public:
int a[2][2];
A();
};
typedef struct{ int a[4]; } array_t;
A::A() {
int at[2][2] = {{1,2},{2,4}};
*(array_t*)a = *(array_t*)at;
}
Ciao
Angelo
Your first variant is extremely close to the right C++11 syntax:
A::A()
: a{{1,2},{2,4}}
{
}
To complement the previous answers (you guys are so fast):
What you were trying to do in case 1 and 2 is array assignment, not permitted, as compiler says ;
But I would like to draw your attention to your third case, that's a grave misconception, specially coming from C as you say.
Assigning to a a pointer to a local variable?
I'm struggling with the constructor of one of my classes do to a member
that is not initialized properly.
I have a class "Settings" that handles the setting I use for my simulations
and a class Simulations that performs the simulation steps.
What I can't understand is why this code doesn't work as expected:
class Settings{
public:
int n ; // a number I need to create properly a vector in my class simulation
// ... rest of the code constructors etc to read values from files.
// everything works fine and the values are assigned properly
}
class Simulation{
public:
std::vector<int> v ;
Settings *SP;
Simulation(Settings *);
}
Simulation::Simulation(Settings *pS)
:SP(pS), v(std::vector<int>(SP->n,0)) {} // the constructor doesn't work,
// v is initialized but it is not created as a vector of size n, but 0.
I think there is a problem in the way I use the constructor but I can't understand why.
By the way defining v inside the curly brackets works fine, I'm just curious to know why
defining it the proper way doesn't work as expected!
Thanks a lot for the help!
You don't need the extra vector:
Simulation::Simulation(Settings *pS)
:SP(pS), v(SP->n,0) {}
If this doesn't work, this isn't your code. Are you sure SP is declared before v in the class definition? If this also doesn't work, try with pS instead of SP.
You've verified that pS->n != 0 prior to instantiating the Simulation, right?
Anyway, I think the line you're looking for in your constructor is:
:SP(pS), v(pS->n, 0) {}
The way you're doing it now is creating a whole std::vector and then copying it to v.
Also please make sure you check SP is not null pointer. This will otherwise have a crash.
Simulation::Simulation(Settings *pS)
:SP(pS), v(pS != NULL ? pS->n : 0 , 0) {}
This will check for SP not being NULL. this is the case when Simulation(NULL) is used as constructor.
You don't need to create an extra vector and use the copy constructor. Just pass the arguments straight to your vector in the member initializer. As another poster mentioned, did you verify that the return of SP->n is actually not 0? If you hardcode some values in, you'll see that it works fine, as below:
#include <iostream>
#include <vector>
using namespace std;
class foo
{
public:
foo();
vector<int> vec;
};
int main()
{
foo obj;
for(int i=0;i<obj.vec.size();++i) {
cout << obj.vec[i] << ' ';
}
system("pause");
return 0;
}
foo::foo()
:vec(vector<int>(10,2))
{
}
I have a specific situation where I've got an object that I want to use the boost random number generators on, and it has lead to a greater question which I cannot seem to answer. Here is the example code of what I'm trying to produce.
First, my header:
Class MyObject {
protected:
double some variable;
boost::random::mt19937 rgenerator;
boost::uniform_real<double> dist_0_1;
boost::variate_generator< boost::mt19937&, boost::uniform_real<double> > rand01
}
Now what I want to do is:
Class MyObject {
protected:
double some variable;
boost::random::mt19937 rgenerator(std::time(0)); //initialize to a "random" seed
boost::uniform_real<double> dist_0_1(0,1); //set the distribution to 0-1
boost::variate_generator< boost::mt19937&, boost::uniform_real<double> > rand01(rgenerator, dist_0_1);//tell it to use the above two objects
}
But this doesn't work because it is in a header. I thought I could use the constructor of MyObject to somehow call the constructors on the various sub-objects (distribution, generator, but I can't figure out how. By the time the constructor of MyObject is called, the sub-objects' default constructors have already been called, and I haven't found that they have member methods to reset these properties... besides which, that isn't the point where I am confused. Now maybe there are too many things going on and I'm confusing issues, but as far as I can tell, my problem reduces to this following, childish example:
Class Tree {
Tree();
Tree(int);
protected:
fruit apples(int);
}
Tree::Tree() {
apples(0); //won't work because we can't call the constructor again?
}
Tree::Tree(int fruit_num) {
apples(fruit_num); //won't work because we can't call the constructor again?
}
Class Fruit {
public:
Fruit();
Fruit(int);
protected:
int number_of_fruit;
}
Fruit::Fruit() {
number_of_fruit = 0;
}
Fruit::Fruit(int number) {
number_of_fruit = number;
}
I'm sure this is second nature to everyone else out there, but I can't find an article that talks about the best practice for initializing member objects of an object to a non-default constructor value.
What you want is an initializer list. For example:
Tree::Tree(int fruit_num)
: apples(fruit_num) // Initializes "apple" with "fruit_num"
{
}
You simply add a colon (:) after the constructor parameters and before the opening brace {. You can separate different member constructors with commas (,). Example:
Tree::Tree(int fruit1, int fruit2) : apples(fruit1), bananas(fruit2) {
}
The answer to this question is relatively straightforwards. You use initializer lists.
Here's an example:
class MyClass {
private:
SomeOtherType sot;
public:
MyClass() : sot(parametersForConstructorOfSOT) {}
};
You can extend this to multiple member objects, of course; it can also be used to call the constructor of a parent class to initialize private entries in a parent class if you need to do something like that.
You're so close! Just use the initialiser list syntax:
Tree::Tree() : apples(0) {
// ...
}
Tree::Tree(int fruit_num) : apples(fruit_num) {
// ...
}
#include <iostream>
using namespace std;
class t
{ public:
int health; //its members
int speed;
int power;
void attack() // its methods
{ cout<<"I'm attacking"<<endl;
};
};
int main()
{ t A,B,C,D;
A.power = 100;
B.health = 87;
C.speed = 92;
cout<<"A= "<<A.power<<"B= "<<A.health<<"C= "<<A.speed<<endl; // <---
cout<< "My health is "<<C.health<<" My speed is "<<A.speed<<endl;
cout<<"My power is "<<B.power<<endl;
D.attack();
system("pause");
return 0;}
The output result was ::
A= 100 B= 96 C=6234392 <--- From where these values come
A.health and A.speed are just junk values on the stack because you didn't explicitly set them. If you want to initialize all fields of A to zero, you can use memset:
memset(&A, 0, sizeof(A));
You should create a constructor to initialize those values to some default value in the initializer list.
class t {
public:
t() : health(100),power(100),speed(100) {}
// ...
};
This will guarantee that those values are all set to 100, or some default, or even an input parameter, rather than garbage. It's considered much better design since otherwise the initialization of those values would be handled in the constructor that the compiler generates for you behind the scenes.
Uninitialized memory?
Uninitialized variable won't be zero setted at the creation of the class/struct. You need to manualy do it. Otherwise, you will get whatever_is_in_memory_at_that_time.