Reputation: 1637
So I'm trying to find the best practice way to have member classes be constructed to on of their derived classes.
struct A {
int a = 0
}
struct B : struct A {
int b = 0;
}
class ContainingClassA {
ContainingClassA() : member_A(){}
virtual A get() {
return member_A;
}
A member_A;
}
class ContainingClassB : public ContainingClassA {
ContainingClassB(){}
virtual B get() override{
return member_A;
}
}
Is there a way of initializing member_A
in class ContainingClassB
such that it is of type B? I've seen perhaps adding a contructor to ContainingClassA
in order to initialize member_A
. I know i could just declare a B member_B
variable in ContainingClassB
and return it, but since B
is derived from A
it seems like I could somehow store it in the inherited variable member_A
...
Upvotes: 0
Views: 97
Reputation: 85541
Is there a way of initializing
member_A
in classContainingClassB
such that it is of type B?
No. member_A
is a member of ContainingClassA
. ContainingClassB
uses the same member_A
from its parent class, ContainingClassA
. You can't change the layout of the parent class.
Also you can't change the declaration of a virtual function (with a few exceptions). In other words, you can't override A get()
with B get()
.
You could change get()
to return a reference instead, then it will be possible to override A& get()
with B& get()
(as A&
and B&
are covariant types).
But first you need to split the solution up into an "interface" and two "implementations" for A and B:
#include <iostream>
struct A {
int a = 0;
};
struct B : public A {
int b = 1;
};
class ContainingClassBase {
public:
virtual const A& get() = 0;
};
class ContainingClassA : public ContainingClassBase {
A member_A;
public:
virtual const A& get() override { return member_A; }
};
class ContainingClassB : public ContainingClassBase {
B member_B;
public:
virtual const B& get() override { return member_B; }
};
int main() {
ContainingClassA a;
ContainingClassB b;
std::cout << a.get().a << std::endl;
std::cout << b.get().b << std::endl;
}
Note also that a solution with allocating A
separately and storing a pointer to it isn't very efficient because it's hard to avoid allocating a spurious A
while constructing ContainingClassB
(the constructor of ContainingClassA
will still be invoked first).
Upvotes: 2
Reputation: 1340
You could use templates to be able to choose the type of the variable. Something like this:
#include <iostream>
struct A {
int a = 0;
};
struct B : A
{
int b = 0;
};
template<typename T>
class ContainingClassA
{
public:
ContainingClassA() : member_A(){}
virtual T get() {
return member_A;
}
T member_A;
};
class ContainingClassB : public ContainingClassA<B>
{
public:
ContainingClassB() { }
virtual B get() override
{
return member_A;
}
};
int main()
{
ContainingClassB cb;
std::cout << cb.get().a;
std::cout << std::endl;
std::cout << cb.get().b;
return 0;
}
Upvotes: -1