While a declaration may be repeated without an effect, there can typically be only one definition:
For illustrative purposes, we'll focus on a class named Simple with a single int data member named val, a default constructor, and
a single member function name getVal.
class Simple;As with function declarations, the main purpose of this is to allow forward (and recursive) class declarations. We will have occasion to use them later, especially in the context of operator overloading.
class Simple {
public:
Simple(int val);
int getVal();
private:
int val; // data members are part of class declaration
};
get/set
functions)
// Simple.h
class Simple {
public:
Simple(int val) : val(val) {} // outside val is data member; inside val is parameter
int getVal() {return val;} // inline function
private:
int val; // data members are part of class declaration
};
this by having a fixed format of the form data-member(expression)
val(val) of the member initialization list of the constructor,
the element outside the parens (val in this case) refers to a data member, while the element inside the parens (again val
here) could be any expression; here it is the parameter.
inline (but need not when the definition is in the class definition):
inline int getVal() {return val;}
inline function definitions may be included multiple times within various files without triggering a multiple-definition error from the linker.
val) refers to those of the receiving object
Simple s1(5), s2(10); // initializes s1's val to 5, and s2's to 10 cout << s1.getVal() << endl; // thevalinsidegetValwill refer to that ofs1cout << s1.getVal() << endl; // thevalinsidegetValwill refer to that ofs2
this in that case
.h file
.cpp file should include the corresponding header file for consistency
of function declarations/headers. The header file would also typically be included in other implementation files that use its facilities. We thus typically have the following situation:
//simple.cpp #include "simple.h" …and
simple_app.cpp #include "simple.h"
This multiple-inclusion of the same header file occurs even within the same file … as an example, almost all applications use strings and
thus would contain a #include <string>. Suppose the app also was using a set of custom string utility function (other than the ones included in the standard C++
string library. Those functions would take string arguments and as the function declarations in the corresponding header file (let's call
it custom_string_utils would make reference to the string class type, it would need a #include in its header file:
// app.cpp
#include <string>
#include "custom_string_utils"
…
// custom_string_utils.h #include <string> void pretty_print(string s); …
When the preprocessor exapands the source file, the header file string is included twice (once from the app's include and the other from the
custom_string_utils' herader file's include.
If there were variable and function definitions in the header file they would trigger multiple-definition errors at link-time.
.h file, and the implementation, i.e., the member function definitions (function bodies) go in the .cpp file.
// Simple.h (interface/header) file
class Simple {
public:
Simple(int val); // headers only
int getVal();
private:
int val; // data members are part of class declaration
};
//Simple.cpp (implementation/source) file
Simple::Simple() : val(val) {}
int Simple::getVal() {return val;}
Simple:: scope resolution operator to:
.h file), while the others are placed
in the corresponding .cpp file
.cpp file is necessary
.h file
class Simple {
public:
Simple(int val); // headers only
int getVal();
private:
int val; // data members are part of class definition
};
inline Simple::Simple() : val(val) {}
inline int Simple::getVal() {return val;}
.h file AFTER the class definition
inline keyword
(so they don't trigger multiple-definition link errors).
class Simple {
public:
Simple(int val); // headers only
int getVal();
private:
int val; // data members are part of class declaration
};
inline Simple::Simple() : val(val) {}
inline int Simple::getVal() {return val;}
class Simple {
…
int val = 0;
};
static (Class) Membersstatic data member and member functions have the same semantics as in Java — there is a single copy of
a static data member for the class, and static member functions take no receiver (instead they are invoked with the class name and
scope resolution operator, e.g. SomeClass::f()) and can only refer to the static data member of the class.
static keyword is used only in the class declaration, the subsequent definition does not contain
static in the header.
.cpp file
// Simple.h
class Simple {
…
static int nextId;
…
};
// Simple.cpp int Simple::nextId = 1000;
using namespace in Header Filesusing statement allows names from the specified namespace to be used without :: qualification.
.cpp file being processed; unlike Java, it does
not go out looking for other files. The only external files it uses are those #include'd within the source file (one can specify when
invoking the compiler which directories it should search for those files, but again, the files themselves are completely specified within the text
of the source file.
As such, all files included in the source file (recursively) and expanded by the preprocessor are essentially 'guests' of the source file and should not
do anything that affects the semantics of that source file. In particular, no header (.h) file should contain a using namespace;
doing so would 'pollute' the namespace of the source file from that point onwards (and most likely without the knowledge of the creator of the source file).
For example, the following header file contains a using. All subsequent appearances of string then resolve to the string type of
the std namespace.
// somefile.h using namespace std; void f(string);
A source file that includes this file will ';silently be resolving string to std::string
//app.cpp #include "somefile.h" // nousingin.cpp… string s; //std::string by virtue of the header's <>code>using …
Instead, the header files should fully qualify any names as necessary:
// somefile.h void f(std::string);
(This is true for actual code contained in inline functions as well)