2

Update 2: Found the forward declare bug that caused this

Update: Compiled using Visual Studio 2010 stock compiler, with c++0x enabled.

I have a class with a member function which is behaving strangely.

When I define the method in the cpp file the linker falls over with an "unresolved external symbol" error. When I move the definition to the header it compiles fine.

1) This is not a templated method 2) The cpp file is definitely being compiled 3) I'm stumped

Any thoughts?

header file

// THIS IS THE ERROR HERE: I forward declare TPA as a class, when it is actually a struct
class TollingPathAttributes; // forward declare the TollingPathAttributes struct as a class (doh!)

class TollingPathAttributesOutput
{
public:
    TollingPathAttributesOutput(HighwayCommand* command);
    ~TollingPathAttributesOutput();

    void foo();
    void AddPathAttributes(boost::shared_ptr<TollingPathAttributes> attributes);

protected:
    string                                      m_outputFilename;
    vector<shared_ptr<TollingPathAttributes>>   m_data;
    queuing_mutex                               m_dataMutex;
};

cpp file

void TollingPathAttributesOutput::foo() {}

void TollingPathAttributesOutput::AddPathAttributes(boost::shared_ptr<TollingPathAttributes> attributes)
{
    queuing_mutex::scoped_lock lock(m_dataMutex);
    m_data.push_back(attributes);
}

invoking call

m_output->foo();  // compiles and links no problem
boost::shared_ptr<TollingPathAttributes> attr = 
    boost::make_shared<TollingPathAttributes>(origin, dest, UNTOLLED_OPTION, vector<int>(), 0.0, 0.0);
m_output->AddPathAttributes(attr); // compiles fine, but only links correctly if I move the definition to the header

link error

1>OtCustomZenith_logic.lib(TollingPathAttributesRecorder.obj) : error LNK2019: unresolved external symbol "public: void __thiscall TollingPathAttributesOutput::AddPathAttributes(class boost::shared_ptr<class TollingPathAttributes>)" (?AddPathAttributes@TollingPathAttributesOutput@@QAEXV?$shared_ptr@VTollingPathAttributes@@@boost@@@Z) referenced in function "public: virtual void __thiscall TollingPathAttributesRecorder::Record(class TolledPath &,class boost::shared_ptr<class Path>,int)" (?Record@TollingPathAttributesRecorder@@UAEXAAVTolledPath@@V?$shared_ptr@VPath@@@boost@@H@Z)     
1>..\..\..\OT\OtCustomZenith_test.exe : fatal error LNK1120: 1 unresolved externals
Jamie Cook
  • 4,375
  • 3
  • 42
  • 53
  • Not on my normal dev. machine so I can't test and this may be just a typo, but m_data is a vector of shared_ptr (not with boost as namespace) while other references have the namespace - may be a problem? – tmpearce Apr 12 '12 at 03:40
  • @tmpearce the explicit boost::shared_ptr was to rule out a mismatch between the call site / header / cpp definitions of the method. In general I have a using boost::shared_ptr somewhere around the place. I'm fairly confident that shared_ptr comes from the boost namespace. – Jamie Cook Apr 12 '12 at 21:16
  • Sounds like a project configuration issue. Does the properties pane read 'File Type: C/C++ Code' and 'Included In Project: True' for the .cpp file? If not, it needs to. – ildjarn Apr 12 '12 at 21:23
  • @ildjarn the cpp file is definitely not being excluded, see http://d.pr/JT4u - also the other method foo compiles and links fine when included in that cpp file. PS thanks for adding the vs tag – Jamie Cook Apr 12 '12 at 22:07
  • I was referring to the property pane, not the property pages window. In any case, there's nothing obvious wrong with the code so I think you'll need to boil this down to an [SSCCE](http://sscce.org) in order to get much assistance. – ildjarn Apr 12 '12 at 22:19
  • Could it be a problem with linking against tbb? (queueing_mutex is being used in the functions you're having problems with.) http://stackoverflow.com/questions/638278/how-to-statically-link-to-tbb may provide hints if this is the case. – tmpearce Apr 13 '12 at 02:16

2 Answers2

4

Thanks to every one who tried to help - unfortunately this error was about 1 foot behind the keyboard. The problem here came down to the use of forward declarations to speed up my compile time. Because I wrongly forward declared the type of TollingPathAttributes as a class instead of a struct.

This meant that the definition of the header was slightly different from the definition in the cpp as I actually included the full definition of TollingPathAttributes in the cpp file. The big thing that confused this issue was that the error messages I received were not what I was expecting to receive - as @MarkRansom says, normally if there is a mismatch between the cpp and header it will be a compile error not a link error so I have to conclude that:

1) the compiler has simply pushed ahead with the incorrect 'class' (rather than 'struct') based definition even though it knows better once it has the full definition available to it. Leading to a lib file that has a signature that is almost but not quite what the linker is looking for.

2) Some other weirdness

Jamie Cook
  • 4,375
  • 3
  • 42
  • 53
0

Judging by the error message your .cpp file is being compiled into a .lib. Is there a possibility that there are two copies of the .lib, one which is being updated with each compile and another that is being linked to your .exe?

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • thanks for the out of the square idea mark, however I don't think this is the case. I added the method foo **after** this problem reared it's head and only provided a definition in the cpp file (the same one i'm trying to define the other method in) and it worked fine... so it's like there is one lib file but it isn't getting the method definition included - or it's being included with a weird signature - maybe I'll have to pull apart the lib to see exactly what is in there. – Jamie Cook Apr 12 '12 at 21:49
  • @JamieCook, it was worth a shot - it's an easy mistake to make. I don't understand how two different functions in the same .cpp could lead to different results. Even if the signature didn't match the one in the header the compiler should complain about it before it gets to the linker. – Mark Ransom Apr 12 '12 at 22:13
  • that is exactly what I thought - hence why I am so flumoxed about this problem - might have to mark it as "unsolved mystery" :) – Jamie Cook Apr 15 '12 at 22:09