Junk values - Inheritance in C++ - c++

I have a class as follows:
class base
{
protected:
int x;
int y;
int z;
public:
base(int x, int y, int z)
{
x = x;
y = y;
z = z;
}
virtual void show();
};
I derive a class from the above as:
class derived : protected base
{
public:
int a;
int b;
int c;
derived(int a, int b, int x, int y, int z) : base(x, y, z) //initialising the base class members as well
{
cout<<a<<b<<x<<y<<z; //works fine
a = a;
b = b;
}
void show()
{
cout<<a<<b<<x<<y<<z; //show junk values
}
//some data members and member functions
};
In main(), I use:
derived d(1, 2, 3, 4, 5);
d.show();
The data members appear to have legal values inside the constructor. However, when I use a similar function, i.e. with the same visibility mode, junk values seem to appear.

a = a;
b = b;
should be
this->a = a;
this->b = b;
or, even better, use an initializer list:
derived(int a, int b, int x, int y, int z) : a(a), b(b), base(x,y,z)
{
cout<<a<<b<<x<<y<<z; //works fine
}
what you're doing is self-assigning the parameter, so the members don't get set.

You never initialize your member variables. a=a; will assign to the local variable a (the parameter), not the member variable. It should be this->a=a;. The same for the other members.

Related

C++ Initialization of member objects which do not have default constructor:

Similar questions have been answered but I still cannot find a solution to my problem. I am indeed not able to call the constructor of class Point inside class Rectangle. After having read some answers, I would approximately do it like this, but it does not work:
class Point {
public:
Point(int x, int y);
private:
int x;
int y;
};
Point::Point(int xx, int yy) {
x = xx;
y = yy;
}
class Rectangle {
public:
Rectangle(Point a, Point b) : Point(int x, int y); // this is wrong
private:
Point a;
Point b;
};
Rectangle::Rectangle(Point aa, Point bb) : Point(int x, int y) { // same as above
?
}
Can anyone help me to understand how to implement and fix this code (I know that declaring Rectangle as a struct makes it way easier)?
It is not clear what you expected this line to do:
Rectangle(Point a, Point b) : Point(int x, int y);
The place to initialize members is not the constructors body. And the correct syntax for the member initiazer list is:
Rectangle(Point a, Point b) : a(a), b(b) {}
Note that the initializer list is a place where shadowing is not an issue, you can use the same name for parameter and member, because there is no ambiguity. a(a) initializes the member a with parameter a.
Note that also constructor of Point should be:
Point::Point(int xx, int yy) : x(xx),y(yy) {
}
For int members it won't make a huge difference, but for class types it does make a huge difference: Members are initialzed before the body of the constructor runs. Fist initializing and then assigning in the constructor is inefficient and sometimes just wrong. On the other hand, there is no reason to not use the initializer list when the members are ints.
PS
(I know that declaring Rectangle as a struct makes it way easier)?
I think you refer to members being public in the struct. However, struct and class are just two different keywords to declare a class. The only difference is default access (see here for details: When should you use a class vs a struct in C++?) and those two definitions are identical:
class foo {
int a;
public:
int b;
};
struct foo {
private:
int a;
public:
int b;
};

Initialize first entries of an array of objects in class constructor initialization list

If I have class A that declares Class B and instantiates an array of it.
class A{
class B{
int x, y;
};
B arrB[10];
public:
A();
};
Then, my issue is that I would like to initialize the first two objects of "arrB" in Class A using initialization list:
A::A(): arrB[0](1, 2), arrB[1](3, 4) {}
But the compiler does not accept it.
Can I initialize specific objects of the array or not? If yes, how to do it?
Thanks
The problem is that B hides its members by default as private because it is a class. Declare B a struct, or expose int x, y as public to be able to use aggregate initialization:
class A{
class B{
public:
int x, y;
};
B arrB[10] = {{1,2}};
public:
A();
};
The second problem is that you're not using aggregate initialization properly.
A::A(): arrB[0](1, 2), arrB[1](3, 4) {}
Should be
A::A(): arrB{{1, 2}, {3, 4}} {}
Demo
In order to initialize an array in the class member initialization list you need to use curly braces like you would if you were initializing an array in a function.
Thus if you wanted to initialize the first and second element of the array you would need to use at least
A() : arrB{{1,2}, {3,4}} {}
as the first set ({1,2}) says make arrB[0] a B with x and y initialized to 1 and 2 respectively. The second set ({3,4}) says make arrB[1] a B with x and y initialized to 3 and 4 respectively.
You do have to do one thing though in order to make this work. You either need to make B and aggregate by making x and y public, or you can provide a constructor for B that takes to values. Doing that lets you have either
class A{
class B{
public:
int x, y;
};
B arrB[10];
public:
A() : arrB{{}, {3,4}} {}
};
int main() {
A a;
}
or
class A{
class B{
int x, y;
public:
B() : x(), y() {} // need this so default instances are value initialized (zeroed in this case)
B(int x, int y) : x(x), y(y) {}
};
B arrB[10];
public:
A() : arrB{{}, {3,4}} {}
};
int main() {
A a;
}

Issue in accessing member variables

#include<iostream>
class A {
int a, b;
public:
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
class B : public A { };
int main() {
A a1;
B b1;
a1.setdata(5, 4);
a1.showdata();
b1.showdata();
}
I just want to print the values of the a and b members using the b1 object of class B, as it can access the member functions of class A since class B has public inheritance of class A. But, I am getting garbage values when I try to print the values of a and b using b1.
Can someone explain why this is happening and how to fix it?
a1 and b1 are completely separate object instances in memory. They have their own copies of the a and b members in memory. They have nothing to do with each other at all. Whatever you do to a1 does not affect b1 at all, and vice versa.
You are initializing the members of a1 only, you are not initializing the members of b1 at all. That is why you are seeing garbage when you try to print out the members of b1.
Before calling b1.showdata(), you need to call b1.setdata() to initialize b1's members, eg:
int main() {
A a1;
B b1;
a1.setdata(5, 4);
a1.showdata();
b1.setdata(1, 2); // <-- add this!
b1.showdata();
}
You should also give class A a default constructor that initializes the members to default values, in case setdata() is not called after construction (such as what happened in your case), eg:
class A {
int a, b;
public:
A() : a(0), b(0) {} // <-- add this!
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
Alternatively, you might consider giving class A and class B a constructor that takes values as input, eg:
class A {
int a, b;
public:
A() : a(0), b(0) {}
A(int x, int y) : a(x), b(y) {} // <-- add this!
void setdata(int x, int y) { a = x; b = y; }
void showdata() { std::cout << a << b; }
};
class B : public A {
public:
B() : A() {}
B(int x, int y) : A(x, y) {}
};
/* or simpler:
class B : public A {
public:
using A::A; // <-- inherit all constructors
};
*/
int main() {
A a1(5, 4);
B b1(1, 2);
a1.showdata();
b1.showdata();
}

Can't access protected member

I have some difficulties understanding the following code. I have 3 classes: A, B and C. A has a private x of type int. B inherits A and everything from it. C inherits from B but protected. This means that both X and Y become inaccessible in class C. Also, get_x() and get_y() become protected in class C. So C should be able to acces the get_x() and get_y() functions but not x and y?
#include<iostream>
using namespace std;
class A
{
int x;
public: A(int i):x(i){}
int get_x(){ return x; }
};
class B: public A
{
int y;
public: B(int i,int j):y(i),A(j){}
int get_y(){ return y; } };
class C: protected B
{
int z;
public: C(int i,int j,int k):z(i),B(j,k){}
int get_z(){ return z; }
};
int main()
{
C c(1,2,3);
cout<<c.get_x();
cout<<c.get_y();
cout<<c.get_z();
return 0;
}
It seems like you understood 'protected inheritance' right but misunderstood 'protected members and methods'.
protected methods are inaccessible from outside of class.
Meaning
C c(1,2,3);
cout << c.get_x(); // THIS DOES NOT WORK.
where you can access get_x() is within class C.
class C: protected B
{
int z;
public: C(int i,int j,int k):z(i),B(j,k){}
int get_z(){ return z; }
int get_x_from_c() { return this->get_x(); } // THIS IS ALLOWED.
};
Here Even Object of type C class can not use the functions of class A and B. If you want access of member functions then make public access of B to C.
do this ...
class c : public B{.. then it will be able to access functions but remember not the member variables.

Virtual multiple inheritance and pointers

Given the following class hierarchy:
class A {
int x;
public:
A(int X) : x(X) {}
void setX(int x) { this->x = x; }
};
class B : public virtual A {
int y;
public:
B(int X, int Y) : A(X), y(Y) {}
};
class C : public virtual A {
int z;
public:
C(int X, int Z) : A(X), z(Z) {}
};
class D : public C, public B {
public:
D(int x, int y, int z) : A(x), C(x,z), B(x,y) {}
};
and the following main:
int main (void)
{
D x(2,3,4);
A* temp1 = &x;
B* temp2 = &x;
C* temp3 = &x;
}
It seems that temp1,temp2 and temp3 are all pointing to different addresses..
Shouldn't B and C share the same A object?
After all, Every C and B object is ALSO an A so the pointers should "see" the A object first.. no?
In addition , the C pointer contains the X's address.. which is a D object. why?
here is the memory map:
&x 0x0036f828 {...} D *
temp1 0x0036f838 {x=5 } A *
temp2 0x0036f830 {y=3 } B *
temp3 0x0036f828 {z=4 } C *
It's just the way the object is represented in memory.
So your object looks like this:
+ 0x0036f828
- D
- int z (C)
- int y (B)
- int x (A)
C++ casting just gives the offset of the beginning of the object.
So you can see that the offset is just the size of an integer for classes A,B,C (because that's what they contain) and a virtual table for classes B,C.
And D doesn't have members, so its offset is 0.
Note that the C++ compiler sets the memory layout by the order you actually write the members and base classes.
So if you'd change the order of the base classes in D, then you'll get different results:
class D : public B, public C
Now B will be the first class in the layout after D.
You're right in that B and C needs to share the same A object. And that is exactly what would happen here. The address that you're seeing is actually the address of a virtual table that is unique to each class. In the case of virtual inheritance, the virtual table of each class would then have a pointer to the virtual base classes, in this case, object A.
So the virtual table of both classes B and C would have a pointer each pointing to the same address of object A.
This is how things might look if written out using plain structs:
struct A {
int x;
};
struct B {
A *ap;
int y;
};
struct C {
A *ap;
int z;
};
struct D {
C c;
B b;
A a;
};
int main (void)
{
D x;
A* temp1 = &x.a;
B* temp2 = &x.b;
C* temp3 = &x.c;
}
Since B and C use virtual inhertiance, they only contain a pointer to the base, and not the actual object. You can see that since c is at the beginning of D, they will have the same address.