I have 4 classes, lets say: class A, class B, class C and class D.
Class B inherits from class A.
Class C and class D inherit from class B.
Classes A and B are abstract classes.
I would like to declare a field in class A, lets say int posision and define this field in constructors of class C and class D by assigning value of the parameter (int parameterValue) to this field.
Is there any solution to do this without duplicating line position = parameterValue in all constructors of descendant classes?
You might use inherited constructor:
struct A
{
A(int position) : position(position) {}
virtual ~A() = default;
int position;
};
struct B : public A
{
using A::A;
};
struct C : public B
{
using B::B;
};
struct D : public B
{
using B::B;
};
Demo
Put it in class B and call the super constructor at the begining of the descendent classes. Like that:
class A {
protected:
int position;
};
class B: public A {
public:
B(int parameterValue) : A() {
position = parameterValue;
}
};
class C: public B {
public:
C(int parameterValue) : B(parameterValue) {
}
};
Related
I have a Class B, which is inheriting Class A.
I have a Class C, which is inheriting Class B and Class A;
There is a variable named "a" in class A which I have to access in class D, but not by using resolution operator on class B for example , d.B::a;
#include<bits/stdc++.h>
using namespace std;
class A{
public:
int a;
};
class B : public A{
public:
int b;
};
class D : public B, public A{
public:
int d;
};
int main() {
D d;
d.B::a = 1; // This is working correctly on this path class D -\> class B -\> class A
d.a = 2;
/*
But This line gives the following error
Non-static member 'a' found in multiple base-class subobjects of type 'A':
class D -> class B -> class A
class D -> class A
*/
return 0;
}
int main() {
D d;
d.D::a = 2; //This is not working correctly on this path class D -\> class A
d.A::a = 2; //This is not working correctly on this path class D -\> class A
//How do I use Scope Resolution to access variable "a" from second path ?!
return 0;
}
B already inherits from A, so D should only inherit from B:
class A{
public:
int a;
};
class B : public A{
public:
int b;
};
class D : public B{
public:
int d;
};
If you had another class C that also inherits from A, and you would want D to inherit from B and C, then you would have the diamond problem. Then, to avoid ambiguity, you should write:
class A{
public:
int a;
};
class B : virtual public A{
public:
int b;
};
class C : virtual public A{
public:
int b;
};
class D : public B, public C{
public:
int d;
};
Virtual inheritance is key words for your problem.
Try this one :
#include<bits/stdc++.h>
using namespace std;
class A{
public:
int a;
};
class B : virtual public A{
public:
int b;
};
class D : public B, virtual public A{
public:
int d;
};
int main() {
D d;
d.B::a = 1; // This is working correctly on this path class D -\> class B -\> class A
d.a = 2;
std::cout << d.a;
/*
But This line gives the following error
Non-static member 'a' found in multiple base-class subobjects of type 'A':
class D -> class B -> class A
class D -> class A
*/
return 0;
}
//In file1.hpp
class A
{
protected:
class B
{
public:
B(int a, int b)
: c(a),
d(b) {}
private:
int c;
int d;
};
};
// In file2.hpp
Class C
{
public:
class D : public A::B --------- This line shows the error that "no matching function for call to B"
{
public:
D() {};
virtual ~D() {};
//something
}
class E : public D
{
E() {};
virtual ~E() {};
}
}
I am getting an error while inheriting the A::B class in D class.
In my main.cpp, I instantiate the D class directly. I am assuming that when D class is instantiated, class A::B gets instantiated automatically.
The error is because I am instantiating D class but not giving the parameters for the instantiation of A::B class.
Right now in main.cpp file, I just write
C::D obj;
My question is, how do I instantiate from main.cpp, the class D and also give parameters for class A::B? I do not want to pass as parameters while instantiating class D. Is there a way to create a method?
In short I can create a method in main.cpp to pass parameters for class A::B but not pass parameters like C::D obj(hi, hey)
First you need to declare "class B" as public and you also need to call calls B constructor from class D (or add defalut constructor)
Sample code:
//In file1.hpp
class A
{
public:
class B
{
public:
//B(){}
B(int a, int b)
: c(a),
d(b) {}
private:
int c;
int d;
};
};
// In file2.hpp
class C
{
public:
class D : public A::B //--------- This line shows the error that "no matching function for call to B"
{
public:
D(): B(1,2)
{};
virtual ~D() {};
//something
};
class E : public D
{
E() {};
virtual ~E() {};
};
};
int main()
{
C c;
return 0;
}
From what I have learnt about virtual inheritance, whenever we have a class A (the base class), classes B, C, D (all these three virtually inherit class A) then if there is a class derived which inherits from B, C and D classes is instantiated then only a single object of class A would be created.
I tried to reason about the virtual inheritance by taking different cases:
Case 1:
Assume the derived class inherits only from class B and C. Even then only a single object of class A gets instantiated, right?
I tried to verify this using this code and it certainly seems to be the case:
#include <iostream>
using namespace std;
class A
{
public:
int a;
};
class B: virtual public A
{
public:
int b;
};
class C: virtual public A
{
public:
int c;
};
class D: virtual public A
{
public:
int d;
};
class derived: public B, public C
{
public:
int y;
};
int main()
{
derived dObj;
cout<<&(dObj.B::a)<<'\n';
cout<<&(dObj.C::a)<<'\n';
return 0;
}
Output:
0x7ffc8adac1c0
0x7ffc8adac1c0
Case 2:
Assume the derived class inherits from class B, C and D, but class D doesn't inherit class A virtually. In this case, 2 objects of class A get instantiated, right? - One for B, C and one for D.
I tried to verify this using this code and it certainly seems to be the case:
#include <iostream>
using namespace std;
class A
{
public:
int a;
};
class B: virtual public A
{
public:
int b;
};
class C: virtual public A
{
public:
int c;
};
class D: public A
{
public:
int d;
};
class derived: public B, public C, public D
{
public:
int y;
};
int main()
{
derived dObj;
cout<<&(dObj.B::a)<<'\n';
cout<<&(dObj.C::a)<<'\n';
cout<<&(dObj.D::a)<<'\n';
return 0;
}
Output:
0x7ffd512429c8
0x7ffd512429c8
0x7ffd512429bc
Now here is my question:
Are my observations correct? That is, instead of just 3 classes - B, C, D, let's assume we have n classes that inherit class A, if out of them, m (1<=m<=n) classes are inherited by another class named derived, and if out of those m classes only k (0<=k<=m) classes inherit class A virtually then the number of objects of class A that get instantiated when instantiating the derived class would be = 1+m-k (if k!=0) and m (when k=0), right?
From the content written in the cppreference website it is indeed the case:
See the first example under the virtual base classes section.
I have written a C++ program.
#include <iostream>
#include <string>
using namespace std;
class A
{
int a;
public:
void read()
{
cin>>a;
}
};
class B:public A
{
public:
B()
{ }
};
class C:public A
{
public:
C()
{}
};
class D:public B,public C
{
public:
void display()
{
cout<<a<<endl;
}
};
void main()
{
A a1;B b1;C c1;
D d1;
d1.display();
}
I get a message saying there is ambiguity. B is inheriting A.. So B class would inherit item 'a' from class A. Also, C class will inherit item 'a' from class A. Now if im trying to inherit both B and C classes in class D, which item 'a' will i be able to access ?? from class B or from class C ?? Is there any way where i can remove the ambiguity .?
You can fix your ambiguity problem by using one of the following options:
Be explicit about the base class
Use B as the explicit base class
void display()
{
cout<< B::a <<endl;
}
or use C as the explicit base class.
void display()
{
cout<< C::a <<endl;
}
Use virtual inheritance
Change B and C to use virtual inheritance.
class B: virtual public A
{
public:
B() {}
};
class C: virtual public A
{
public:
C() {}
};
Suppose I have:
class A {
public:
A(int x_) : x(x_) {}
int x;
};
class B: public A { };
class C: public A { };
With this code, B and C won't have any constructors (other than the copy constructor). I would like to change something in class A (not in B or C) so that both B and C will inherit the constructor of A. Is that possible somehow?
It is not possible to have them implicitly. You can explicitly have the constructors available via:
class B: public A { using A::A; };
class C: public A { using A::A; };