0

there doesn't seem to be a decent way to google this so here's my issue:

.cpp files include .h files. So lets say I have a class defined in range_search.h, and implement it in range_search.cpp. Not if I want to use it from another cpp file I, again, include range_search.h. This seems to be the right etiquette anyway. This way though, I'm not including the .cpp file anywhere, and currently my code is complaining about not finding the functions therein. What am I doing wrong?

Best, and thanks in advance! Alex

EDIT: As per wish:

range_search.h:

#ifndef RANGE_SEARCH_H_
#define RANGE_SEARCH_H_

namespace range_search {

template<class Point>
class RangeSearch {
 public:
    using value_type = Point;

    virtual void assign(const std::vector<Point>& points) = 0;  
};

}  // namespace range_search
#endif  // RANGE_SEARCH_H_

range_search.cpp:

#include "range_search.h"

namespace range_search {

    /// Sets the underlying set.
    void assign(const std::vector<Point>& points){
        //doing stuff
    }  
}

main.cpp:

#include "range_search.h"

using Point = std::array<double, 2>;

int main(){

    //initialize some points
    range_search::RangeSearch<Point> r();
    r.assign(points);

}

Error is in German unfortunately:

Fehler: Abfrage des Elementes »assign« in »r«, das vom Nicht-Klassentyp »range_search::RangeSearch >()« ist r.assign(points);

From what I can tell it's due to the fact that main.cpp has no link to range_search.cpp

Alex
  • 45
  • 6
  • Your description is not clear to me. You should post a minimum code that may reproduce your problem, and how you compiled your code – Donghui Zhang Oct 13 '16 at 21:10
  • 2
    In light of the fact that 0 is round and feminine, while 1 is straight and masculine, the current masculine dominance of the information technology field can be reversed simply by switching 0 and 1 in all computers, placing the 1's in the lower, non-dominant position. Switching the roles of .h and .cpp files would then not be necessary. I think. – Cheers and hth. - Alf Oct 13 '16 at 21:11
  • The cause for that error is that `range_search::RangeSearch r();` declares a function that takes no parameters and returns a `range_search::RangeSearch`. As the error says, `r` does not have a class type. Use `range_search::RangeSearch r;` – molbdnilo Oct 13 '16 at 21:27

2 Answers2

0

This seems to be the right etiquette anyway. It's not a matter of etiquette, but .cpp files are considered as translation units and handled as such by any decent compiler or build system.

The .h files contain all the declarations needed to be seen for use in other translation units.

The compiled .cpp files are stitched together in the final linking phase.

This way though, I'm not including the .cpp file anywhere, and currently my code is complaining about not finding the functions therein. What am I doing wrong?

You probably missed to get that last part of linking the generated object files right.


As for your edit:

You're showing a template declaration now, which is a more special case. The compiler needs to see the template definitions to get them instantiated correctly.

You can read more about the details here: Why can templates only be implemented in the header file?

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
0

This comes down to the way that C++ (and C for that matter) build. Your compiler will compile .cpp files into object files (typically .o or .obj). The linker then links multiple object files into a single binary (executable or library).

Your compiler (linker actually) is complaining that it can't find the definition of the functions you're calling because those object files aren't being included in the link. Or so it seems from your question, hard to say without the actual error (in future, do include actual error messages please).

We include .h files so the declaration (not definition usually) of various things (classes, functions, what have you) is visible to the compiler. If you didn't include those, the compiler would complain that things declared in those headers weren't declared, so it doesn't know what they're supposed to be.

I'll try to run down some documentation about this. For the moment, check the docs for your compiler/IDE. They should have information about linking multiple object files.

  • 3
    Nitpick: headers usually have class *definitions*, with the definitions of their member functions in the `.cpp` file. `struct foo { int a; void bar(); };` is a class definition. – juanchopanza Oct 13 '16 at 21:16
  • @juanchopanza Isn't that still called a _class declaration_? – πάντα ῥεῖ Oct 13 '16 at 21:18
  • @πάνταῥεῖ It is both a declaration and a definition. But a definition is usually required. A declaration that is not a definition is `struct foo;`. – juanchopanza Oct 13 '16 at 21:19
  • Yes, that's true. For anyone who's not familiar with declarations vs definitions, the corresponding declaration of @juanchopanza's example definition is `struct foo;`. Ninja'd me – Chris Kimberley Oct 13 '16 at 21:20
  • @juanchopanza Ah, I see. But I'm always mentioning that as a _forward declaration._ – πάντα ῥεῖ Oct 13 '16 at 21:22