0

I am trying to compile some old source code from another person in my lab. And I cannot really understand the idea of the following trick. Why somebody wants to access CLog2Factory class trough the reference given by gLogFactory()? And how can I successfully compile and link the code below?

The whole code is big, so I made a short example. Keep friend and virtual as they present in original code.
test.h:

class CLog2;

class CLog2Factory
{
    friend class CLog2;
public:
    CLog2Factory() {}
    virtual int init() = 0;
};

CLog2Factory&   gLogFactory();

class CLog2
{
public:
    CLog2() : gLogFactory().init()
        { }
};

test.cpp:

#include "test.h"

int main(int argc, char *argv[])
{
    CLog2 log;

    return 0;
}

I get the following error:

test.h: In constructor ‘CLog2::CLog2()’: test.h:50:15: error: class ‘CLog2’ does not have any field named ‘gLogFactory’
     CLog2() : gLogFactory().init()
               ^ 
test.h:50:28: error: expected ‘{’ before ‘.’ token
         CLog2() : gLogFactory().init()

In fact, I could compile the original code (perhaps I am missing something in my test example). but couldn't link it. Error from linking of original code is the following(file test.h is changed to Log2.h now):

Log2.h:254: undefined reference to `gLogFactory()'
Ivan
  • 599
  • 4
  • 18
  • Constructor initializer lists are for initializing data members. – chris Aug 18 '14 at 14:48
  • Does `CLog2Factory& gLogFactory()` really compile??? Wow. – barak manos Aug 18 '14 at 14:51
  • @barakmanos Followed with a semi-colon, it is a forward declaration of a function returning a reference to `CLog2Factory`. – Chnossos Aug 18 '14 at 14:53
  • @Chnossos: Yep, I see that now... thought it was an attempt to declare a global variable by reference or something (my mistake in not reading carefully)... Thanks – barak manos Aug 18 '14 at 14:54
  • @chris ok, got it, and this seems to be the difference with original code. In original they use `CLog2(const std::string &name) : mStream(gLogFactory().getLog(name)) { } – Ivan Aug 18 '14 at 14:55
  • @chris if I move gLogFactory().init() to the body of constructor, i get a linker error. how can i solve it? and what are the benefits of this code? – Ivan Aug 18 '14 at 14:57
  • You are getting an undefined reference because you declared `CLog2Factory& gLogFactory();` but you didn't define it. – clcto Aug 18 '14 at 14:59
  • You solve the linker error by linking with the definition of `gLogFactory`. – molbdnilo Aug 18 '14 at 14:59
  • @Ivan: The link error is because you haven't defined the `gLogFactory` function (or aren't linking with the file that defines it). – Mike Seymour Aug 18 '14 at 14:59
  • Your real problem probably boils down to something already answered [here](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – chris Aug 18 '14 at 15:06

1 Answers1

2

Your code is missing something from the original : a member (which as the type returned by the init() method) is initialized by this initialization list, something like :

class CLog2
{
public:
    CLog2() : x(gLogFactory().init())
        { }

    int x;
};
quantdev
  • 23,517
  • 5
  • 55
  • 88