Reputation: 291
A few days ago, I wanted to dive into the C++ world. I'm studying the base and derived class concepts. Could someone explain the nuance going on with the following two code snippets?
class A
{
private:
virtual int GetValue() { return 10; }
public:
int Calculate() { return GetValue()*1.5; }
};
class B: public A
{
private:
virtual int GetValue() { return 20; }
};
int main()
{
B b;
std::cout << b.Calculate() << std::endl;
return 0;
}
The output is 30 but 15 was expected
class A
{
private:
int m_data;
public:
A(): m_data(GetValue()) {}
int Calculate() { return m_data*1.5; }
virtual int GetValue() { return 10; }
};
class B: public A
{
public:
virtual int GetValue() { return 20; }
};
int main()
{
B b; A* ap;
ap=&b;
std::cout << ap->Calculate() << std::endl;
return 0;
}
The output is 15 but 30 was expected
Can someone explain and help me understand the reasoning? Something is wrong with my thinking on this concept, but I am unable to figure it out.
Upvotes: 8
Views: 508
Reputation: 2138
Try the following code for the second example:
class A
{
private:
int m_data;
public:
A(): m_data(GetValue()) { std::cout << "Init m_data and A ";}
int Calculate() { return m_data*1.5; }
virtual int GetValue() { std::cout << "GetValue from A ";return 10; }
};
class B: public A
{
public:
B() { std::cout << "Init B "; }
virtual int GetValue() { std::cout << "GetValue from B"; return 20; }
};
int main()
{
B b; A* ap;
ap=&b;
std::cout << ap->Calculate() << std::endl;
return 0;
}
It is the same as you already have but with outputs. You should get GetValue from A Init m_data and A Init B 15
. I hope now you see why you have an output of 15
. With the outputs you should be able to reconstruct the execution order.
Upvotes: 2
Reputation: 234635
First case:
This is trivial. You have an instantiated instance of B
, and you compute return GetValue() * 1.5;
which uses B::GetValue()
as you've marked GetValue()
to be virtual
in the base class. Hence 20 * 1.5 is evaluated.
Second case:
Not so trivial. You are calling GetValue()
in the base member initialiser to set a value for m_data
. Standard C++ dictates that the base class GetValue()
method will be called in that case. (Informally think of this as being due to class B
not being constructed until class A
is fully constructed). Hence 10 * 1.5 is evaluated. Interestingly, if GetValue()
was pure virtual, then the behaviour of the program would have been undefined.
Upvotes: 5