Why does this member function behave differently when defined in a header file?

Viewed 70

I had been using a header file to contain a class's entire definition just for throwing things together.

The function in question is GetLocalCentroidOnShell(); a public member of the class Cell. Like everything else in the class, I wrote its definition in Cell.h.

I discovered that if I called GetLocalCentroidOnShell() from some other member function in the same class, it behaved properly. But if I instead called GetLocalCentroidOnShell() through a different class's object, it would return incorrect values.

This is a simple test:

void APlanetOfCells::TestCentroidLocations() const
{
    for (int32 i = 0; i < 5; ++i)
    {
        UE_LOG(LogTemp, Log, TEXT("Cell %d:"), i);

        // Call GetLocalCentroidOnShell() from right here
        FVector centroid = Cells[i].GetLocalCentroidOnShell();
        UE_LOG(LogTemp, Warning, TEXT("Planet object says centroid is --> %s."), *centroid.ToString());

        // Call GetLocalCentroidOnShell() from inside the cell object instead
        Cells[i].PrintCentroid();
    }
}

... where PrintCentroid is also a Cell member function, simply doing the same thing as the test's code:

void Cell::PrintCentroid() const
{
    FVector centroid = GetLocalCentroidOnShell();
    UE_LOG(LogTemp, Warning, TEXT("Cell object says centroid is ----> %s."), *centroid.ToString());
}

Results:

LogTemp: Cell 0:
LogTemp: Warning: Planet object says centroid is --> X=16.683 Y=75.035 Z=63.190.
LogTemp: Warning: Cell object says centroid is ----> X=16.683 Y=75.035 Z=63.190.
LogTemp: Cell 1:
LogTemp: Warning: Planet object says centroid is --> X=-49.525 Y=114.088 Z=126.379.
LogTemp: Warning: Cell object says centroid is ----> X=-66.207 Y=39.053 Z=63.190.
LogTemp: Cell 2:
LogTemp: Warning: Planet object says centroid is --> X=48.347 Y=128.999 Z=117.164.
LogTemp: Warning: Cell object says centroid is ----> X=97.871 Y=14.911 Z=-9.215.
LogTemp: Cell 3:
LogTemp: Warning: Planet object says centroid is --> X=122.630 Y=185.318 Z=82.356.
LogTemp: Warning: Cell object says centroid is ----> X=74.284 Y=56.319 Z=-34.807.
LogTemp: Cell 4:
LogTemp: Warning: Planet object says centroid is --> X=210.574 Y=213.893 Z=45.813.
LogTemp: Warning: Cell object says centroid is ----> X=87.944 Y=28.575 Z=-36.543.

The Planet and Cell lines in each pair should be identical.

The fix was to move the definition of GetLocalCentroidOnShell() out of the header file and into a source file. So instead of this in Cell.h (which returns wrong values):

FVector GetLocalCentroidOnShell() const
{
    FVector sum = FVector();

    for (int32 edge = 0; edge < ShellEdgesWithNeighbours.Num(); ++edge)
    {
        sum += ShellEdgesWithNeighbours[edge].EdgeStartPosition;
    }

    return sum / static_cast<float>(ShellEdgesWithNeighbours.Num());
}

... I have this in Cell.cpp (which is a straight Ctrl-C, Ctrl-V, and returns correct values):

FVector Cell::GetLocalCentroidOnShell() const
{
    FVector sum = FVector();

    for (int32 edge = 0; edge < ShellEdgesWithNeighbours.Num(); ++edge)
    {
        sum += ShellEdgesWithNeighbours[edge].EdgeStartPosition;
    }

    return sum / static_cast<float>(ShellEdgesWithNeighbours.Num());
}

Results:

LogTemp: Cell 0:
LogTemp: Warning: Planet object says centroid is --> X=6.923 Y=65.276 Z=53.430.
LogTemp: Warning: Cell object says centroid is ----> X=6.923 Y=65.276 Z=53.430.
LogTemp: Cell 1:
LogTemp: Warning: Planet object says centroid is --> X=-66.207 Y=39.053 Z=63.190.
LogTemp: Warning: Cell object says centroid is ----> X=-66.207 Y=39.053 Z=63.190.
LogTemp: Cell 2:
LogTemp: Warning: Planet object says centroid is --> X=97.871 Y=14.911 Z=-9.215.
LogTemp: Warning: Cell object says centroid is ----> X=97.871 Y=14.911 Z=-9.215.
LogTemp: Cell 3:
LogTemp: Warning: Planet object says centroid is --> X=74.284 Y=56.319 Z=-34.807.
LogTemp: Warning: Cell object says centroid is ----> X=74.284 Y=56.319 Z=-34.807.
LogTemp: Cell 4:
LogTemp: Warning: Planet object says centroid is --> X=87.944 Y=28.575 Z=-36.543.
LogTemp: Warning: Cell object says centroid is ----> X=87.944 Y=28.575 Z=-36.543.

The question:

Why does defining GetLocalCentroidOnShell() in the header file lead to different behaviour?

I do not know if this is a C++ thing, a compiler thing, an Unreal thing, or perhaps something else.

Using VS2017 & UE 4.25.

0 Answers
Related