Reputation: 64
I have two base classes and derivered versions that overload / override certain parts like this:
class base
{
public:
int X = 1;
};
class deriv : public base
{
public:
int X = 2;
};
class A
{
public:
base K;
virtual void doSmth()
{
std::cout << "A" << std::endl;
smthElse();
}
virtual void smthElse()
{
std::cout << K.X << std::endl;
}
};
class B : public A
{
public:
deriv K;
void doSmth()
{
std::cout << "B" << std::endl;
smthElse();
}
};
the application looks like this
int main()
{
A instanceA;
B instanceB;
instanceA.doSmth();
instanceB.doSmth();
getchar();
return 0;
}
And the output therefore is X=1 for both instances A
and B
. I was wondering why that is.
A
uses base
(X=1) and B
uses deriv
(X=2). deriv
overloads X
and B
overloads K
. Is this because the function smthElse()
is only defined in A
, thus A
can't know about the existance of the overloaded variable K
?
If so, is there a way for the function smthElse()
to use the overloaded variable K
?
I found the using
keyword but also adding a using A::smthElse;
in B
won't change the behaviour of X
not being printed as 2. The only way I can achieve this is by copying the function smthElse()
from A
and insert it into B
.
Is there a different way to achieve what I'm looking for? Since it seems like an overkill to copy'n'paste the same function into B
just to use an overridden variable.
Thanks in advance!
Upvotes: 0
Views: 52
Reputation: 206577
instanceB
has two variables named K
, A::K
and B::K
. However, the base class, A
, only knows about one K
, A::K
.
That explains the output.
If so, is there a way for the function
smthElse()
to use the overloaded variable K?
Yes, you can do that by adding a virtual
function in A
that returns a reference to base
and adding a virtual function in base
that returns a reference to i
.
class base
{
public:
int& getX( return X;}
private:
int X = 1;
};
class deriv : public base
{
public:
int& getX( return X;}
private:
int X = 2;
};
class A
{
public:
base& getK() { return K; }
virtual void doSmth()
{
std::cout << "A" << std::endl;
smthElse();
}
virtual void smthElse()
{
std::cout << getK().getX() << std::endl;
// ^^^^^^^^^^^^^ use the virtual functions
}
public:
base K;
};
class B : public A
{
public:
deriv& getK(){ return K; }
void doSmth()
{
std::cout << "B" << std::endl;
smthElse();
}
public:
base K;
};
PS I hope this is just curiosity and you don't write production code with such style. You will end up confusing yourself and anybody who tries to understand your code.
Upvotes: 2
Reputation: 40070
When you write
virtual void smthElse()
{
std::cout << K.X << std::endl;
}
smthElse
is virtual
K
is not (a member variable could not be virtual
: it has no meaning for an attribute).In other terms, it means that B::smthElse
will ovevrride A::smthElse
but B::K
and A::K
are two distinct, unrelated and independent variables.
When smthElse
is called in the context of a B
, K
still means A::K
.
As a solution, you might create a virtual accessor to K
s:
class base { ...};
class deriv{ ...};
class A
{
base K;
public:
virtual const base& theK() { return K; }
virtual void smthElse() { std::cout << theK().X << "\n"; }
};
class B : public A
{
deriv K;
public:
virtual const base& theK() { return K; }
};
When B{}.smthElse()
is called, it will call B::theK()
which will return B::K
(a deriv instance
).
Upvotes: 0