johnbakers
johnbakers

Reputation: 24750

Why does this cpp see a function when its corresponding header does not?

This one is making me scratch my head too long.

I have the following in a header test.h:

inline void anything(){
std::cout<<" anything "<<ii;
}

Then I have a.h, which includes test.h:

class Fooness{
public: 
Fooness(){
    anything(); //compiler reports "use of undeclared identifier"
    };
};

HOWEVER, if I simply move the function definition to a.cpp:

Fooness::Fooness(){
anything();
}

It works. a.cpp includes test.h which includes a.h. Why is anything() only visible in a.cpp not a.h?

Upvotes: 2

Views: 93

Answers (2)

leemes
leemes

Reputation: 45665

As you pointed out in the comments, you included a.h in test.h and vice versa. This introduces errors as functions and classes being "undefined" because of a cyclic dependency, also known as cross-include.

In your case, when a .cpp file includes test.h, it first includes a.h and then defines the function anything();, which is obviously not what you want, since when processing a.h, anything() is undefined.

Your code expands to something similar to this, when compiling a unit which includes test.h (before a.h), which by itself includes a.h before anything else:

/* INCLUDED FROM a.h */
class Fooness{
public: 
Fooness(){
    anything();
    };
};

inline void anything() {
    ....
}

As you see, there is no anything() defined when you use it. However, if a compilation unit includes a.h (before test.h), which itself includes test.h, it expands to something like this:

/* INCLUDED FROM test.h */
inline void anything() {
    ....
}

class Fooness{
public: 
Fooness(){
    anything();
    };
};

So the order is correct.

To make it work in both situations, you can forward-declare anything() in test.h before you include a.h:

Corrected version of test.h:

#ifndef TEST_H
#define TEST_H

void anything(); // forward-declaration

#include "a.h"   // <-- this is important to be *below* the forward-declaration

inline void anything() {
    ....
}

// more stuff

#endif

Then, when including test.h (before a.h), it expands to the following:

void anything();

/* INCLUDED FROM a.h */
class Fooness{
public: 
Fooness(){
    anything();
    };
};

inline void anything() {
    ....
}

Upvotes: 2

zaufi
zaufi

Reputation: 7119

make sure that "undeclared identifier" is about anything() and not about ii which I see in operator<<...

Upvotes: 1

Related Questions