Given the following situation:
struct A
{
const float x;
const float y;
A(float x, float y)
: x{x}, y{y} {}
};
class B
{
public:
B(const float& floating)
: floating{floating} {}
virtual float foo_x() const = 0;
virtual float foo_y() const = 0;
virtual A foo() const
{
return A(foo_x(), foo_y());
}
protected:
const float& floating;
};
class C : public B
{
public:
C(const int* integer, const float& floating)
: B{floating}, integer{integer} {}
virtual float foo_x() const override
{
return static_cast<float>(*integer) floating 1.0f;
}
virtual float foo_y() const override
{
return static_cast<float>(*integer) - floating - 2.0f;
}
private:
const int* integer;
};
int main()
{
float F{1.0f};
int I{1};
C object(&I, F);
A res{object.foo()};
}
is there anything wrong with the definition of foo()
? The snippet above produces the expected result (res
holding 3
and -2
), but a similar setup in a bigger project is producing some unexpected results upon calling foo()
, while giving the correct output if I call separately foo_x()
and foo_y()
from C
(I'm sorry I've not been able to reproduce the bug in a minimal way).
Am I invoking some undefined behavior by calling foo_x()
and foo_y()
inside the definition of foo()
in B
? Seems to me that, as foo()
is ultimately called by C
, the vtable should be resolved correctly, but maybe I'm missing something.
CodePudding user response:
Am I invoking some undefined behavior by calling foo_x() and foo_y() inside the definition of foo() in B?
No. This is well defined and works the way you expect it to, as long as all regular preconditions for calling virtual functions are met.
The easiest mistake to make with regard to these preconditions is that the subclass, C
in this case, must be fully constructed before the virtual
call is made.