I have a basic question with the flow of constructors w.r.t. inheritance in C++.
The classes are defined as follows:
Base class A is defined as follows. It has 2 constructors - A() and A(int x). A(int x) calls A().
class A {
protected:
int a;
public:
A() {
a = 0;
}
A(int x) {
A();
a = x;
}
};
Derived class B is derived from Base class A. It has 2 constructors - B() and B(int x, int y).
B() calls A() in addition to setting member variable b to 0.
B(int x, int y) calls A(x)
class B : public A {
protected:
int b;
public:
B() : A() {
b = 0;
}
B(int x, int y) : A(x) {
B();
b = y;
}
void print() {
std::cout << "a=" << a << ",b=" << b << std::endl;
}
};
int main() {
B b(1, 2);
b.print();
}
Output:
a=1,b=2
Expected:
a=0,b=2
I am expecting the flow as below,
B b(1, 2) ->
B(int x=1, int y=2) ->
A(int x=1) ->
A() sets a=0 ->
A(int x=1) sets a = 1 ->
B() ->
A() overwrites a=0 -> <===== Shouldn't a=0 get reflected in final output ?
B() sets b = 0 ->
B(int x=1, int y=2) sets b = 2
However, I am seeing a=1 and b=2.
Does anyone know what is that I am missing in this code flow?
#EDIT:#
Perhaps the better way to do this is as #Jarod42 suggested. The code is updated below. It is still unclear how come the above code is able to get a=1 and b=2. Dry runs indicate that we should be getting a=0 and b=2.
class A {
protected:
int a;
public:
A() : A(0) {
}
A(int x) {
a = x;
}
};
class B : public A {
protected:
int b;
public:
B() : B(0, 0) {
}
B(int x, int y) : A(x) {
b = y;
}
void print() {
std::cout << "a=" << a << ",b=" << b << std::endl;
}
};
Instead of
A(int x) {
A(); ...
you have to delegate to the other constructor with :
A(int x) : A() {
...
Same within class B. Hope this solves your question.
Related
I have a Base class A, 2 childs B and C that both inherits from A, and I have a class D that inherits from both B and C in which I want to take _a from B and _b from C without having to do a virtual method for print_a and print_b if possible
# include <iostream>
class A
{
public:
A(void) : { }
~A(void) { }
inline void print_a(void) { std::cout << _a << std::endl; }
inline void print_b(void) { std::cout << _b << std::endl; }
protected:
int _a;
int _b;
};
class B : virtual A
{
public:
B(int a) : A() { _a = a, _b = 0; }
~B(void) { }
protected:
using A::_a;
using A::_b;
};
class C : virtual A
{
public:
C(int b) : A() { _a = 0, _b = b; }
~C(void) { }
protected:
using A::_a;
using A::_b;
};
class D : virtual public A, private B, private C
{
public:
D(void) : A(), B(5), C(5) { }
~D(void) { }
private:
using B::_a;
using C::_b;
};
int main(void)
{
D foo;
foo.print_a();
foo.print_b();
return (0);
}
My D class is inheriting methods print_a and print_b from A and I want it to inherit _a = 5 from B and _b = 5 from C, but it doesn't work, it outputs:
0
5
Instead of:
5
5
As you are using virtual for all base classes you end up with D having only one A (and not one as base of D, one as base of B and one as base of C).
The problem is with your constructors.
The constructor of a derived class calls the constructors of all base classes in the order they are given in the base class list, so in your case D::D calls:
A::A() -> _a and _b uninitialized
B::B(5)
_a = 5
_b = 0
C::C(5)
_a = 0
_b = 5
It is unclear why you are setting _a and _b multiple times in different constructors. It would be better to initialize members in the constructor's member initializer list and not assign it in a constructor body. You could for example write
A(int a, int b) : _a(a), _b(b) {}
B(int a) : A(a, 0) {}
C(int b) : A(0, b) {}
D() : A(5, 5), B(5), C(5) {}
Here D::D() would result in
A(5, 5) -> _a initialized to 5, _b initialized to 5
B(5) -> no effect (on A/_a/_b)
C(5) -> no effect (on A/_a/_b)
If you want to stick with your design and initialize the variables in the constructor bodies, you can simply add code to D::D to overwrite whatever the base class constructors set:
D() : A(), B(5), C(5) { _a=5; _b=5; }
I'm new to polymorphism and I'm trying to learn how this exactly works .
I want for example to get the print() function of class Y and use it in the base class .
Is this possible to do ?
class A
{
public:
A() = default;
virtual void print()
{
//Is it possible to get the print() function of class Y here ?
};
};
class B : public A
{
public:
B() = default;
void print(){ std::cout << "B " << std::endl;}
};
class C : public A
{
public:
C() = default;
void print(){ std::cout << "C " << std::endl;}
};
class Y : public C , public B
{
public:
Y() = default;
void print()
{
B::print();
C::print();
}
};
int main()
{
A a;
a.print();
return 0;
}
Your main() is creating an A object directly, not a Y object. That is why you are not seeing the output you want. Polymorphism only works when accessing derived class objects via base class pointers/references, eg:
int main()
{
Y y;
A *a = static_cast<C*>(&y);
a->print();
return 0;
}
int main()
{
Y y;
A &a = static_cast<C&>(y);
a.print();
return 0;
}
The reason for the type cast is becauseY has 2 A portions, one from B and one from C, so you have to help the compiler a little by specifying which A you want to point to.
When I construct an object D I need to include the constructors for A, B, and C in the initializer list. Is there any way to make it so that I don't need all three in the initializer list or not?
If I try to initialize D using only a constructor for B I get an error because I don't have a default constructor for A or C. If I add a default constructor for A and C I get issues with "i" being reinitialized with no value.
#include <iostream>
using namespace std;
class A
{
int i;
public:
A(int ii) :
i(ii)
{}
~A() { }
int getI() { return i; }
};
class B : public virtual A
{
public:
B(int ii) :
A(ii)
{ }
~B() { }
};
class C : public virtual A
{
public:
C(int ii) :
A(ii)
{ }
~C() { }
};
class D : public B, public C
{
public:
D(int ii) :
A(ii), B(ii), C(ii)
{ }
~D() { }
};
int main()
{
D d(45);
cout << d.getI() << endl;
}
If you add default constructors to A, B, and C, the implmentation of D becomes a bit simpler.
#include <iostream>
using namespace std;
class A
{
int i;
public:
A() : i(0) {}
A(int ii) : i(ii) {}
~A() { }
int getI() { return i; }
};
class B : public virtual A
{
public:
B() { }
B(int ii) : A(ii) { }
~B() { }
};
class C : public virtual A
{
public:
C() { }
C(int ii) : A(ii) { }
~C() { }
};
class D : public B, public C
{
public:
// Relies on default constructors of the other classes.
D() { }
// Relies on the default constructors of B and C.
D(int ii) : A(ii) { }
~D() { }
};
int main()
{
D d1(45);
D d2;
cout << d1.getI() << endl;
cout << d2.getI() << endl;
}
I'm afraid not. With virtual inheritance, your most-derived class must initialise the virtual base.
Read more here.
How about adding a default value to the A, B, C constructors, i.e.
A(int ii=0) :
#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();
}
Given the following code in C++:
struct A {
A() { f(0); }
A(int i) { f(i); }
virtual void f(int i) { cout << i; }
};
struct B1 : virtual A {
B1(int i) : A(i) { f(i); }
virtual void f(int i) { cout << i+10; }
};
struct B2 : virtual A {
B2(int i) : A(i) { f(i); }
virtual void f(int i) { cout << i+20; }
};
struct C : B1, virtual B2 {
int i;
C() : B1(6),B2(3),A(1){}
virtual void f(int i) { cout << i+30; }
};
Can someone explain why C* c = new C(); will print 1 23 and then 16 in that order? How does it decide which order to print in? I know that the nonvirtual B1 will be called last but why is A() called first? Thanks for the help and explanation ahead of time.
Because your are virtually inheriting B2, the compiler will construct it first as to identify which variables are virtually inherited in C before it constructs any non-virtual inheritance (B1). Of course, A gets constructed first because B2 needs it before it can be constructed.