I have three files -- main, a header and its 'implementation':
// main.cpp
#include "word_indexer.h"
int main() {
WordIndexer wd;
cout << wd.size() << endl;
return 0;
}
// word_indexer.h
class WordIndexer {
public:
int size() const; // declaring a function
};
// word_indexer.cpp
class WordIndexer {
public:
int size() const {return 0;}
};
Building with g++ -o main main.cpp word_indexer.cpp yields
undefined reference to 'WordIndexer::size() const'
Replacing the implementation with
// updated word_indexer.cpp
class WordIndexer {
public:
int size() const;
};
int WordIndexer::size() const {return 0;}
fixes the problem.
I cannot figure out the difference between these word_indexer.cpp and its updated versions, they seem to be identical.
Why does the first variant have linking problems?
There is no need to repeat the definition of the class in its implementation file. Just have it include the header the class is defined in and then define the member functions in the implementation file like:
// word_indexer.cpp
#include "word_indexer.h"
int WordIndexer::size() const {return 0;}
As for why the first variant did not work: Member functions defined in a class are implicitly inline. Thus, their definitions must be present in every translation unit that uses them. This is why this works if you define the member in the class in the header file, but not if you only have the inline definition in another .cpp file.
Here's how it's usually done for classes.
Header (word_indexer.h):
// declare the class and all its methods, member variables, etc.
class WordIndexer {
public:
int size() const; // declaring a function, but not its implementation
};
Implementation (word_indexer.cpp):
// the implementation basically takes the header "skeleton" and fleshes it out;
// to do that, of course, we need the skeleton first
#include "word_indexer.h"
// we don't need to say "class WordIndexer {}" or anything like that,
// because that's already been done in the header we included
// implement the method
int WordIndexer::size() const {return 0;}
In word_indexer.cpp you should have written something like:
int WordIndexer::size() const {return 0;}
That's the actual definition syntax.
And instead of redeclaring WordIndexer in the translation unit, just #include "word_indexer.h".
Related
I have a number of templatic and inline functions defined in an header file (let's call it head.h). Currently, these functions use some global variables declared with extern in the same header and defined somewhere in one .cpp.
Everything works fine, but I would limit global variables scope only to the header where they are defined.
In other words every other .h or .cpp that includes my head.h wouldn't be able to see such globals.
Any way to achieve this result?
including header files just copies the content of the header file into the including cpp/h file. That means, you cannot really distinguish whether you do something in your header file or in a cpp/h file that includes your header file.
So, variables that are defined in a header file cannot be excluded. If they are in a cpp file and you would like to forbid extern, you could use an anonymous namespace:
namespace
{
int variable;
}
Best practice, obviously, would be to not use global variables at all. It is considered bad style for several reasons like readability, hard to determine dependencies, difficulties with testing, a really bad chance of extending your software and so on. So, you might reconsider this kind of architecture for your next project if refactoring is not an option here.
One way would be to put a class around it instead of a namespace, making all functions public static methods of that class and the global variables private static variables.
i.e.:
head.h:
class A
{
public:
template <typename T> static void MethodA(T const &value)
{
//...
}
inline static void MethodB(int a, int b)
{
// ...
}
private:
static int x;
static std::string y;
};
head.cpp:
int A::x = 0;
std::string A::y;
EDIT:
Another alternate method would be to define the globals as private static variables in a class and make all functions that are allowed to use them friend functions:
head.h:
template <typename T> void FunctionA(T const &value);
void FunctionB(int a, int b);
class Vars
{
friend template <typename T> void FunctionA(T const &value);
friend FunctionB(int a, int b);
private:
static int x;
static std::string y;
};
template <typename T> void FunctionA(T const &value)
{
// ...
// ... A::x ...
// ...
}
inline void FunctionB(int a, int b)
{
// ...
// ... A::y ...
// ...
}
head.cpp:
int A::x = 0;
std::string A::y;
No, it is not possible.
If you declare some variable as extern in a header1.h - this variable will be available in any other headers which include header1.h.
in a book i am reading to learn basic c++, there is this example:
#include <iostream>
using namespace std;
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y);
int get_x();
int get_y();
};
void Point::set(int new_x, int new_y) {
x = new_x;
y = new_y;
}
int Point::get_x() {
return x;
}
int Point::get_y() {
return y;
}
My question is, is it not possible in c++ to include the definition of the member functions inside the class itself? The above seems quite messy. The book says to define a class member function you should use 'return_type class_name::function(){arguments}. But in C# you can just do it within the same class and it is less code. I haven't been able to find much about properties in c++. Thanks for help.
Although it is possible, it's not really recommended. Actually, the way it's done in your book isn't how it should be done either (and hopefully, later on in the book that will change!). The way you'll see it done 99% of the time (yes, I pulled that number out of my ass) is a class definition in a header file (.h extension) and the definitions in a source file (.cpp extension). The header file will be imported so to speak, into the source file via #include.
You can define the members within the class as such.
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y) {
x = new_x;
y = new_y;
}
int get_x() { return x; }
int get_y() { return y; }
};
However, this isn't a popular style of coding in C++. Most C++ conventions suggest that you separate the implementations (definitions) from the interface (the declarations) in different files (definitions would go into Point.cpp, and declarations would go into Point.h), unless the definitions are very short (like accessors).
You can define functions in the class definition in C++. This will cause them to be inline implicitly but that shouldn't matter because compilers have flexibility in terms of actually inlining. Usually this isn't done because it will increase compile time due to larger amounts of code being processed and the canonical C++ way it to put the method definitions in a separate source file.
class Point
{
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y)
{ x = new_x; y = new_y; }
int get_x()
{ return x; }
int get_y()
{ return y; }
};
of course you can write
#include <iostream>
using namespace std;
class Point {
private: // Data members (private)
int x, y;
public: // Member functions
void set(int new_x, int new_y)
{
x = new_x;
y = new_y;
}
int get_x()
{
return x;
}
int get_y()
{
return y;
}
};
But whole point is to separate declaration and implementation.
Yes we can Define a function inside a class.it has following advantage.
1)the function which you define inside a class is treated as an "inline" function .
(inline keyword before any function suggest compiler to place body of the definition of the function to where ever that function is been called from at compile time)
2)due to which inline function execute Faster.then normal function.
(remember its totally up to the compiler to make that function inline or not.you cannot force compiler to make it inline)
Most answers point out that it is possible but not recommended, I do not agree with the latter. For simple one-liner accessors it just makes sense to provide them inside the class definition in most cases:
class point {
int x,y;
public:
// ...
int posX() const { return x; }
int posY() const { return y; }
};
As of the setters, it will depend on whether you want to verify any invariant or not. In the former case, you might want to move it to a single translation unit, but even there if the checks are small I would just inline them inside the class definition.
The recommendations for separating declaration and definition of the member methods include things like:
smaller compile time: false, the compiler can parse the accessor trivially, it will not add much more to the parsing
smaller code size: false, if the function is not inlined, then the compiler must generate code for the function call, including calculation of the this pointer and actually perform the call. The inlined accessor will just require the reading of the member which will take less code.
higher compile time coupling: any change in the implementation of the function will require recompilation of all translation units that include the header... True, if you change the function, which for such a simple accessor will not happen.
I have this class that has a static member. it is also a base class for several other classes in my program. Here's its header file:
#ifndef YARL_OBJECT_HPP
#define YARL_OBJECT_HPP
namespace yarlObject
{
class YarlObject
{
// Member Variables
private:
static int nextID; // keeps track of the next ID number to be used
int ID; // the identifier for a specific object
// Member Functions
public:
YarlObject(): ID(++nextID) {}
virtual ~YarlObject() {}
int getID() const {return ID;}
};
}
#endif
and here's its implementation file.
#include "YarlObject.hpp"
namespace yarlObject
{
int YarlObject::nextID = 0;
}
I'm using g++, and it returns three undefined reference to 'yarlObject::YarlObject::nextID linker errors. If I change the ++nextID phrase in the constructor to just nextID, then I only get one error, and if I change it to 1, then it links correctly. I imagine it's something simple, but what's going on?
Make sure you are linking against the generated .o file. Double-check the makefile.
I am a bit of a newbie in C++, but I just stumbled on the following.
If I have these files:
myclass.hpp:
class myclass {
public:
myclass();
void barf();
};
mymain.cpp:
#include "myclass.hpp"
int main() {
myclass m;
m.barf();
return 0;
}
And I use this implementation of myclass:
myclassA.cpp:
#include <iostream>
using namespace std;
class myclass { // or include myclass.hpp, it both works fine
public:
myclass();
void barf();
};
myclass::myclass() { } //empty
void myclass::barf() {
cout << "barfing\n";
}
then everything is OK. But if I use this implementation of myclass, which is exactly the same except the members are defined inside the class definition, I get a linking error:
myclassB.cpp:
#include <iostream>
using namespace std;
class myclass {
public:
myclass() { }
void barf() {
cout << "barfing\n";
}
};
The error I get:
$ g++ myclassB.cpp mymain.cpp
/tmp/cc4DTnDl.o: In function `main':
mymain.cpp:(.text+0xd): undefined reference to `myclass::myclass()'
mymain.cpp:(.text+0x16): undefined reference to `myclass::barf()'
collect2: ld returned 1 exit status
Apparently the object file built from myclassB.cpp doesn't export the member functions. Why aren't both of these implementations behaving te same? Is there some gotcha rule in C++ that says member definitions inside class definitions are not globally visible, but they are if they are defined outside of the class?
standard that says that there must be a unique definition of a class,
template, etc., is phrased in a somewhat more complicated and subtle manner. This rule is commonly referred to as ββthe one definition rule,ββ the ODR. That is, two definitions of a class, template,
or inline function are accepted as examples of the same unique definition if and only if
[1] they appear in different translation units, and
[2] they are tokenfortoken
identical, and
[3] the meanings of those tokens are the same in both translation units.
For example (valid):
// file1.c:
struct S { int a ; char b ; };
void f(S* p){ }
// file2.c:
struct S { int a ; char b ; };
void f(S* p){ }
Examples that violate ODR:
file1.c:
struct S 1 { int a ; char b ; };
struct S 1 { int a ; char b ; }; // error: double definition
This is an error because a struct may not be defined twice in a single
translation unit.
// file1.c:
struct S 2 { int a ; char b ; };
// file2.c:
struct S 2 { int a ; char b b ; }; // error.
This is an error because S2 is used to name classes that differ in a member name.
// file1.c:
typedef int X ;
struct S 3 { X a ; char b ; };
// file2.c:
typedef char X ;
struct S 3 { X a ; char b ; }; // error.
Here the two definitions of S3 are
token for token identical, but the example is an error because the
meaning of the name X has sneakily been made to differ in the two files.
Member functions defined inline are candidates to be inlined by the compiler. If it's never used, and only defined inline inside of a source file, I suspect your compiler is removing the method altogether.
That being said, I highly recommend putting your declaration in a header file, and just have the definitions in your .cpp files. Include the header file (with the appropriate guards, such as #pragma once or #idfef/#define guards. You will need to do this as your projects get larger, so it's best to just build the appropriate practices now.
In addition to Jagannaths answer, I thought the definition of myclass in myclass.hpp counted as a declaration, but in C++ it is a definition so Jagannaths answer applies. It turns out it is possible to just declare a class but then you can only use pointers or references to that class, but not access its members in any way. see also: Declare a C++ class without defining it in the current translation unit
SingleList.h
#include "ListBase.h"
#include "DataNode.h"
#include "SingleListIterator.h"
namespace list
{
class SingleListIterator;
class SingleList : public ListBase
{
private:
DataNode *head;
DataNode *tail;
public:
SingleList();
SingleList(const SingleList &obj);
~SingleList();
void Flush(); //deletes all elements in the list
void PushInFront(const int data); // **
void Append(const int data); // **
void DeleteLast();
void DeleteFirst();
int Delete(const int& data); // ** remove the first occurrence of data and return 1 otherwise 0
const int& GetFirst() const; // **
int& GetFirst(); // **
const int& GetLast() const; // **
int& GetLast(); // **
void PrintList() const;
const int IsEmpty() const;
// SingleList<T> &operator=(const SingleList<T>& obj) (**)
// const int operator==(const SingleList<T> &obj) const (**)
// const int operator!=(const SingleList<T> &obj) const (**)
// SingleList<T>& operator+(const SingleList<T> &obj) (**) // concatenates two lists
// operator int() // returns list size (**)
friend class SingleListIterator; // ** ASK Changd it from Iterator
};
SingleListIterator.h
#include "Iterator.h"
#include "SingleList.h"
namespace list
{
class SingleList;
class SingleListIterator: public Iterator
{
public:
// error here --> Forward declaration of 'const struct list::SingleList'
SingleListIterator(const SingleList &list); // **
SingleListIterator(const SingleListIterator &obj); // **
virtual const int Current() const; // **
virtual void Succ();
virtual const int Terminate() const;
virtual void rewind();
// T &operator++(int) (**)
// SingleListIterator<T>& operator=(const SingleListIterator<T>&obj) (**)
};
// error here --> Invalid use of incomplete type 'list::SingleList'
SingleListIterator::SingleListIterator(const SingleList &list) : Iterator(list.head)
{
}
Errors indicated in code
Also what can I do in a case like this where there is mutual coupling between two header files ?????
Thaaaaanks
You use forward declarations, but you anyway include the .h files recursively. The point of the forward declarations is that you don't need to include the headers of the
forward declared class, thereby breaking the mutual dependency.
Also it should be enough to use a forward declaration for one of the classes, not for both of them.
I would suggest the following structure:
SingleListIterator.h:
class SingleList; // forward declaration
class SingleListIterator {
// Declarations, only using pointers/references to SingleList.
// Definitions that need to know the structure of SingleList (like maybe
// a constructor implementation) need to be done in the .cpp file.
};
SingleList.h:
#include "SingleListIterator.h" // include full declaration
class SingleList {
// declarations
};
SingleListIterator.cpp:
#include "SingleListIterator.h"
#include "SingleList.h" // include full declaration of the type
// forward-declared in SingleListIterator.h
// method definitions,...
SingleList.h:
#include "SingleList.h" // include full declarations of everything
// definitions
This way there are no files that mutually include each other and all types are completely known in the implementation (.cpp) files.
The problem is that the SingleListIterator::SingleListIterator(const SingleList &) constructor needs to know about the head member of SingleList, so it needs the full declaration of the class.
You can:
Move the constructor definition to a separate source file.
Just include SingleList.h instead of using a forward declaration. As long as SingleList.h is okay with a forward declaration, you don't also need to use one in SingleListIterator.h.
Also, you're both including the header files AND providing forward declarations. You only need one or the other (stick to a forward declaration if you only need references or pointers to the type and no access to the type's member variables or functions).
You're on the right track to solving this problem in general. The important part is that X.h doesn't include Y.h if Y.h also must include X.h.
You want to separate your declaration into header files and your definition into .cpp files.
Put this inside your .cpp:
SingleListIterator::SingleListIterator(const SingleList &list) : Iterator(list.head)
{
}
As a general rule, you can also always use a pointer type with just having the forward declaration.
Don't include SingleListIterator.h from SingleList.h. The forward declaration for it in SingleList.h is sufficient. You don't need the definition of SingleListIterator in SingleList.h.
(I'm assuming you have some sort of "include guard" in place that you've omitted in the snippet.)
(I'll let everyone else point out all the other things that are poor about this snippet.)