Learning C++ and see the class laid out like this:
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area () {return (x*y);}
};
void CRectangle::set_values (int a, int b) {
x = a;
y = b;
}
I know Java and methods(functions) in Java are written within the class. The class looks like a Java interface. I know I can write the class like this:
class CRectangle {
int x, y;
public:
void set_values (int a, int b) {
x = a;
y = b;
};
int area () {return (x*y);}
};
But is there a difference or standard?
There's a difference. When you write the definition of the function within the class definition (case 2), then the function is considered to have been declared inline. This is standard C++.
Usage, is to declare the member functions (Java methods) within the class definition, in a header file (.h), and to define these member functions in a C++ file (.cpp, .cc, or .C, …) This reduces compilation time, when you change the body of a function, only the C++ file has to be compiled, whereas if you change something in the header file, all C++ files that include this header are to be compiled.
It's much cleaner if you only define prototypes in the class definition (which belongs into a header file) and implement the methods in a cpp file.
When you have very small classes doing everything in the class definition might sound easier since everything is at the same place, but as soon as your class grows any developer using it will hate you since he'll have your code between the method prototypes he might look at to find out something (not everyone uses an IDE which shows all available methods!).
However, there is one exception: Template class methods needs to be implemented in the header as they need to be compiled for every specialization of the template.
The usual way is to put the implementation of functions within a separate cpp file, which is not included by other files, just compiled. This way it is easier to manage dependencies.
If the implementation of a function is given within the class definition (as in your 2nd example), this is a hint for the compiler to inline that function (which it may or may not do in the end, depending on e.g. the internals of the function). As a rule of thumb, function bodies longer than a few lines of code are better put into the cpp file, as these are probably not going inlined, however these may include extra dependencies and clutter the class definition.
The exception is template functions, where the bodies need to be in the header too, for the compiler must see them in order to instantiate the template.
I believe that if the method body is inside the class definition, then it is inlined everywhere is it called.
In C++, member functions which are defined in class are implicitly inline, member functions defined outside the class are not.
This affects the linkage of your two examples - the linker will complain about multiple definitions if the first example is #included in multiple source files, whereas the second example will not.
In terms of what's standard/normal:
The first form is used for complex classes, where the implementation of the functions requires extra headers to be pulled in.
The second form is used for simple classes which don't have extra dependencies.
Either form is used for template classes based on developer preference.
There is a slight difference in that functions defined inside the class are automatically inline. The latter definition can be put into a separate file. Otherwise there is no difference nor preference.
Note that we usually don't write semicolons after function definitions (though they are allowed inside a class definition).
void set_values (int a, int b) {
x = a;
y = b;
} // no semicolon here
Related
what's the difference between the following 3 cases:
1) in point.h:
class point
{
int x,y;
public:
int getX();
};
int point::getX() {
return this->x;
}
2) in point.h:
class point
{
int x,y;
public:
int getX()
{
return this->x;
}
};
3) in point.h:
class point
{
int x,y;
public:
int getX();
};
int point.cpp:
int point::getX() {
return this->x;
}
Note: I read that it's somehow connected to inline but not sure which one of them makes the compiler to treat int getX() and inline int getX()
Avoid this first one:
struct point
{
int x,y;
int getX();
};
int point::getX() {
return this->x;
}
If multiple source files include point.h, you will get multiple definitions of point::getX, leading to a violation of the One Definition Rule (and modern linkers will give an error message).
For the second one:
struct point
{
int x,y;
int getX()
{
return this->x;
}
};
This implicitly inlines the function. This means that the function definition may be copy-pasted everywhere it is used, instead of resolving a function call. There are a few trade offs here. On one hand, by providing definitions in headers, you can more easily distribute your library. Additionally, in some cases you may see performance improvements due to the locality of the code. On the other hand, you may actually hurt performance due to instruction cache misses (more instructions around == it won't all fit in cache). And the size of your binaries may grow as the inlined function gets copied around.
Another tradeoff is that, should you ever need to change your implementation, all clients must rebuild.
Finally, depending on the sensitivity of the function, you may be revealing trade secrets through your headers (that is, there is absolutely no hiding of your secret sauce) (note: one can always decompile your binary and reverse engineer an implementation, so putting the def in the .cpp file won't stop a determined programmer, but it keeps honest people honest).
The third one, which separates a definition into a .cpp file:
// point.h
struct point
{
int x,y;
int getX();
};
// point.cpp
int point::getX() {
return this->x;
}
This will cause a function to get exported to your library (at least for gcc. In Windows, you need to be explicit by using __declspec directives to import/export). Again, there are tradeoffs here.
Changing the implementation does not require clients to recompile; you can distribute a new library for them to link to instead (the new library is ABI-compatible if you only change the impl details in the .cpp file). However, it is more difficult to distribute your library, as your binaries now need to be built for each platform.
You may see a performance decrease due to the requirement to resolve function pointers into a library for running code. You may also see a performance increase over inlining due to the fact that your code may be friendlier to the instruction cache.
In the end, there is a lot to consider. My recommendation is to go with #3 by default unless you are writing templates. When you want to look at improving performance, you can start to measure what inlining does for you (binary size as well as runtime perf). Of course you may have other information up front that makes approach #2 or #3 better suited for the task (e.g., you have a Point class, and you know that accessing X will happen everywhere and it's a really small function, so you decide to inline it).
what's the difference between the following 3 cases
The function definition is outside of the class definition. Note that in this example you've defined a non-inline function in a header. Including this header into more than one translation unit violates the One Definition Rule. This is most likely a bug.
The function definition is inside of the class definition. In this case, the function is implicitly inline. As such, it is fine to include it into multiple translation units.
The function definition is outside of the class definition again. The function is not declared inline. This time the function is defined in a separate translation unit, thereby conforming to the ODR even if the header is included into multiple translation units.
what's the problem if both b.cpp & a.cpp includes my header file
The problem is that then both b.cpp and a.cpp will define a non-inline function. The One Definition Rule says that there must be at most one definition of any inline function. Two is more than one. Therefore doing this violates the ODR and therefore such program would be ill-formed.
I'm too much confused why it's an error to write the same function in two different cpp files?
It is an "error" because the rules of the language (explained above) say that it is an "error".
what if both want to use that function?
Then declare the function in both translation units. Only define the function in one translation unit unless you declare the function inline, in which case define the function in all translation units (where the function is used) instead. Look at the examples 2. and 3. of your question to see how that can be done.
so the code in method 1 is not automatically inlined?
No. Functions are not automatically declared inline. Function is declared inline only if A. inline keyword is used, or if B. it is a non-static member function that is defined within the class definition (or in a case involving constexpr that I shall omit here). None of those cases apply to the example 1, therefore it is not an inline function.
I find it a very appealing programming style define all the methods of a struct/class directly inline in the struct, eg only define structs this way:
"A.hpp"
class A;
"A.cpp"
class A
{
A() = default;
void method() { }
};
rather than
"A.hpp"
class A
{
A();
void method();
};
"A.cpp"
A::A() = default;
void A::method() { }
This means putting classes/struct definitions in a code file and only including declaration in header files.
However, this runs into the problems when the compiler would need to know the struct/class layout in other code files.
Is there a programming style that supports this? Perhaps only getting and setting fields through getters/setters? This way would however lead to large amounts of boilerplate.
Just including the struct/class definition in the header file leads to issues with mutually recursive header files, unless one explicitly puts the declarations in another.
I can achieve this programming style in a language like D with a module system, but how does one achieve it in C++?
What are you doing is called forward declaration.
You will be not able to do anything (f.e. call methods, create instances) with this class in all other translation units, except one .cpp file, where you define it. So, this idea is completely useless and bad. And you will get a boatload of linker errors.
So, you need to either stick to style #2. Or define inline methods in header file, like this
struct A {
A() {} // something
int func() { /* function body */
}
Consider the following four member function declarations and definitions:
// ==== file: x.h
#ifndef X_H
#define X_H
class X {
public:
int a(int i) { return 2 * i; }
inline int b(int i) { return 2 * i; }
int c(int i);
int d(int i);
};
inline int X::c(int i) { return 2 * i; }
int X::d(int i) { return 2 * i; }
#endif
For completeness, here's the .cpp file that instantiates an X and calls the methods...
// ==== file: x.cpp
#include "x.h"
#include <stdio.h>
int main() {
X x;
printf("a(3) = %d\n", x.a(3));
printf("b(3) = %d\n", x.b(3));
printf("c(3) = %d\n", x.c(3));
printf("d(3) = %d\n", x.d(3));
return 0;
}
My question: are there any salient differences among the four methods? I understand from a comment in this post that the compiler may automatically inline methods that are defined in the class definition.
update
Many answers assume that I'm asking about the difference between inlining and not. I'm not. As I mentioned in the original post, I understand that defining a method in the header file gives the compiler license to inline the method.
I also (now) understand that method d is is risky as written: since it is not inlined, it will be multiply defined if there are multiple translation units.
My question remains: are there any salient differences among the four methods? (As noted, I know that method d is different). But -- just as important -- are there stylistic or idiomatic considerations that would make a developer choose one over the others?
Since this answer keeps getting upvotes, I feel obligated to improve it. But much of what I'm adding has already been stated in other answers and comments, and those authors deserve the credit.
On the subject of whether there's a difference between placing a function body inside the class definition or just below it (but still in the header file), there are 3 different cases to think about:
1) The function is not a template and is not declared to be inline. In this case it must be defined in the class definition or a separate cpp or you will get a linker error as soon as you try to include the h in more than one compilation unit.
2) The function is a template, but is not declared inline. In this case, putting the body within the class definition provides a hint to the compiler that the function can be inlined (but the final decision is still at its own discretion).
3) The function is declared to be inline. In this case there is no semantic difference, but it may sometimes be necessary to place the function body at the bottom in order to accommodate dependency cycles.
Original answer, which provides good info but does not address the actual question:
You've already noted the inline difference. In addition, defining member functions in the header means your implementation is visible to everyone. More importantly, it means everyone who includes your header also needs to include everything needed to make your implementations work.
If you are going to inline it regardless, then you'd move it out of the class if you want to be able to see all your members in one screen, or you have a cyclic dependency as mentioned below. If you don't want to inline it, then you have to move it out of the class and into an implementation file.
In the cases of classes that cyclically refer to each other, it may be impossible to define the functions in the classes so as to inline them. In that case, to achieve the same effect, you need to move the functions out of the classes.
Doesn't compile:
struct B;
struct A {
int i;
void foo(const B &b) {
i = b.i;
}
};
struct B {
int i;
void foo(const A &a) {
i = a.i;
}
};
Does compile, and achieves the same effect:
struct B;
struct A {
int i;
inline void foo(const B &b);
};
struct B {
int i;
inline void foo(const A &a);
};
inline void A::foo(const B &b) {
i = b.i;
}
inline void B::foo(const A &a) {
i = a.i;
}
Oops, just realised you had the definitions in the header file. That creates problems if the include file is included in more than one place.
If the functions are defined in a CPP file then there is no difference.
The only time it makes sense to implement a function inline is when the function is very clearly trivial and/or it has performance implications.
For all other times, it's best to put them in a .cc file and keep its implementation not exposed to the user of the class.
As pointed out by user3521733, it is impossible to implement some functions in the header file when there are cyclic dependencies. Here you are forced to put the implementations in a .cc file.
Update
As far as the compiler, and the runtime, is concerned, there is no difference that I can think of between defining the function inside the body of the class or outside if you use inline when defining it outside the body of the class.
X::a, X::b and X::c are all inlined. X::d is not. That's the only real differnce between these functions, aside from the fact that they are all different functions. The fact that X::c is defined in the header is irrelevant. What is relevant there is that the definition is marked inline.
In order to understand what the differences are, it's important to understand what inline is and is not. inline is not a performance tweak. It's not about making your code faster, and it's not about blowing the code out inline.
What it is about is the ODR. A function marked inline will have the exact same definition in each translation unit where it is used.
This comes in to play when you try to #include your file above in two or more CPP files and call X::d in those translation units. The linker will complain that X::d is defined more than once -- you've violated the ODR. The fix to this is to either mark the function inline or move the definition to it's own translation unit. (eg, to a CPP file)
I am working on a codebase that is not my own, that has the following layout:
object.h:
// Objects are defined
// #include "tickets.h" (functions to access the objects)
// An access-handler object is defined
I want to introduce a class that knows about the objects, can be accessed from functions in tickets.h, but can also use the access-handler object. The functions are separate, i.e. class functions that are called in tickets.h do not use the access-handler (I wouldn't know where to start if that weren't the case).
Therefore my class needs to be defined before tickets.h, but some of its functions need to be defined after the access-handler. Is there a way to do this without splitting it up into two header files something like the following:
// Objects are defined
// -- include declaration of class, and definition of functions that tickets.h needs
// #include "tickets.h"
// An access-handler object is defined
// -- include functions of class that need the access-handler
This seems very messy splitting things up like this into two separate files, I was hoping to keep everything contained.
Thanks for any help, I clearly only have a very rudimentary understanding of declarations/definitions in c++.
EDIT: If I use forward declaration and include it before tickets.h (with the class declared in mynewclass.h and functions defined in mynewclass.cc) will mynewclass.cc be able to use objects declared after the inclusion of mynewclass.h? Namely the access-handler object.
EDIT2: Something like this:
object.h:
class obj { // definition }
#include "tickets.h"
class obj_handler {
public void handle { // code }
}
tickets.h:
void do_something(obj o){
communicator.foo();
}
My object (communicator):
class communicator {
public:
void foo() { // code }
void bar() { // use handle() from obj_handler }
}
As you can see, my communicator needs to be used in tickets.h, but can't be defined until after obj_handler. So where should I include it?
If I correctly understand your question - you can use forward declaration to solve this problem. This will allow you to declare some class before defining it's methods. For example:
// this is forward declaration of class A, no definition provided
class A;
class B
{
// uses A
A * a_;
};
// class A definition
class A
{
// may use class B now
B * b_;
};
I'm not quite sure whether I understand this right and don't have enough reputation here yet to make this a comment, so let me try to answer your question this way, please feel free to follow up if I'm guessing wrong:
I believe what you are referring to is an entire class definition, i.e., one including all function definitions within the class declaration. Other than that, it is not very common to see object definitions followed by preprocessor directives. What is typical though is a forward declaration of functions and a class prototype.
So, for example, you could declare in some header.h:
class C
{
public:
void method1(void);
int method2(void);
};
And in some implementation.cpp the definition of the functions like:
void C::method1(void) { /*...*/ }
In the other file preceded in the inclusion chain by your access-handler you then define the other function:
int C::method2(void) { /*...*/ }
What do you mean by access-handler, by the way?
Oh, and your linker likely will yell somewhat at you if you do function definition in a header file.
With regard to your addenda: everywhere you put a forward declaration, loosely speaking, the compiler will insert a copy of the declaration in question, consider it a soft link in the context of file systems. There are negative implications associated with it, like increased duration and the memory load of compilation if you have many forward declarations of the function signature or class. It's impossible to tell whether this will word in your particular situation since only you know the actual code in question. But most likely it would work.
Take a look at these pages:
http://en.wikipedia.org/wiki/Forward_declaration
When can I use a forward declaration?
I'm trying to create a C++ class, with a templated superclass. The idea being, I can easily create lots of similar subclasses from a number of superclasses which have similar characteristics.
I have distilled the problematic code as follows:
template_test.h:
template<class BaseClass>
class Templated : public BaseClass
{
public:
Templated(int a);
virtual int Foo();
};
class Base
{
protected:
Base(int a);
public:
virtual int Foo() = 0;
protected:
int b;
};
template_test.cpp:
#include "template_test.h"
Base::Base(int a)
: b(a+1)
{
}
template<class BaseClass>
Templated<BaseClass>::Templated(int a)
: BaseClass(a)
{
}
template<class BaseClass>
int Templated<BaseClass>::Foo()
{
return this->b;
}
main.cpp:
#include "template_test.h"
int main()
{
Templated<Base> test(1);
return test.Foo();
}
When I build the code, I get linker errors, saying that the symbols Templated<Base>::Templated(int) and Templated<Base>::Foo() cannot be found.
A quick Google suggests that adding the following to main.cpp will solve the problem:
template<> Templated<Base>::Templated(int a);
template<> int Templated<Base>::Foo();
But this does not solve the problem. Adding the lines to main.cpp does not work either. (Though, interestingly, adding them to both gives 'multiply defined symbol' errors from the linker, so they must be doing something...)
However, putting all the code in one source file does solve the problem. While this would be ok for the noddy example above, the real application I'm looking at would become unmanageable very fast if I was forced to put the whole lot in one cpp file.
Does anyone know if what I'm doing is even possible? (How) can I solve my linker errors?
I would assume that I could make all the methods in class Templated inline and this would work, but this doesn't seem ideal either.
With templated classes, the definitions must be available for each translation unit that uses it. The definitions can go in a separate file, usually with .inl or .tcc extension; the header file #includes that file at the bottom. Thus, even though it's in a separate file, it's still #included for each translation unit; it cannot be standalone.
So, for your example, rename template_test.cpp to template_test.inl (or template_test.tcc, or whatever), then have #include "template_test.inl" (or whatever) at the bottom of template_test.h, just before the #endif of the include guard.
Hope this helps!
The problem is that when your Templated file is compiled, the compiler doesn't know what types it will need to generate code for, so it doesn't.
Then when you link, main.cpp says it needs those functions, but they were never compiled into object files, so the linker can't find them.
The other answers show ways to solve this problem in a portable way, in essence putting the definitions of the templated member functions in a place that is visible from where you instantiate instances of that class -- either through explicit instantiation, or putting the implementations in a file that is #included from main.cpp.
You may also want to read your compiler's documentation to see how they recommends setting things up. I know the IBM XLC compiler has some different settings and options for how to set these up.
The C++ FAQ-lite covers this, and a couple of ways round it.
You don't have to make all the methods "inline", but you should define the method bodies in template_test.h, rather in template_test.cpp.
Some compilers can handle this split, but you have to remember that at one level, templates are like macros. for the compiler to generate the a template for your particular , it needs to have the template source handy.
When the compiler is compiling main.cpp, it sees the class definition has member function declarations, but no member function defintions. It just assumes that there must be a definition of "Templated" constructor and Foo implementation somewhere, so it defers to the linker to find it at link time.
The solution to your problem is to put the implementation of Templated into template.h.
eg
template<class BaseClass>
class Templated : public BaseClass
{
public:
Templated(int a) : BaseClass(a) {}
virtual int Foo() { return BaseClass::b; }
};
Interestingly, I could get your code to link by putting this at the end of template_test.cpp.
void Nobody_Ever_Calls_This()
{
Templated<Base> dummy(1);
}
Now the compiler can find an instance of Templated to link with. I wouldn't recommend this as a technique. Some other file might want to create a
Templated<Widget>
and then you'd have to add another explicit instantiation to template_test.cpp.