Post

[C++] Chap 14 - Separate Compilation and Namespaces

[C++] Chap 14 - Separate Compilation and Namespaces

Seperate Compilation

  • Program parts
    • kept in separate files
    • Compiled separatedly
    • Linked together before program runs
  • Class Definitions
    • Separate from “using” programs
    • Build Library of classes → Re-used by many diffrerent programs, just like predefine libraries
  • Encapsulation principle
    • Separate how class is used by programmer from details of class’s implementation
    • “Complete” separation : change to implementation does not impact on any other programs
    • Basic OOP principle

Class separation

  • Interface file
    • Contains class definition with function and operator declarations/prototypes
    • Users “see” this
  • Implementation File
    • Contains member function definitions

Class header files

  • Class interface always in header file : use .h naming convention
  • Programs that use the class will “include” it
  • #include "myclass.h"
  • Quote(””) indicate you wrote the header
  • Use <> with predefined library header file

Class Implementation files

  • Class implementation in .cpp file
  • Typically give interface and implementation file same name.
  • All class’s member function are defined here
  • Implementation file must #include the class’s header file
  • Class header file #included by:
    • Implementation file
    • Program file (Often called “application file” or “driver file”
    • The one that has the main function

Multiple compiles of Header files

  • Header files typically included multiple times. (e.g. class interface included by class implementation and program file)
  • But it must be compiled once.
  • There’s no guarantee which #include in which file the compiler might see first.
  • Use preprocessor to tell compiler to include header only once

Using #ifndef

1
2
3
4
#ifndef FNAME_H
#define FNAME_H
...
#endif
  • FNAME is typically the name of the file
  • This syntax avoids multiple definitions of header file

Namespaces

  • A collection of name definitions
    • Class definitions, variable declarations
  • Programs use many classes and functions, Commonly they may have same names
  • Namespaces deal with this. Namespaces can be “on” or “off”
  • using namespace std; : Makes all definitions in std namespcae available

Namespace std

  • Contains all names defined in many standard library files
  • #include <iostream>
    • Places all name definitions(cin, cout, etc) into std namespace
    • Must specify the namespace for program to access names

Global Namespace

  • All code goes into some namespace
  • Unless specified : global namespace
    • No need for using directive
    • Global namespace always available

Specifying Namespaces

1
2
3
4
5
6
7
8
{
	using namespace NS1;
	myFunction();
}
{
	using namespace NS2;
	myFunction();
}
  • using directive has block-scope

Creating a Namespace

1
2
3
4
5
6
namespace Namespacename
{
	Some Code
}

using namespace Namespacename;

Multiple names

  • If name is defined in both namespaces
    • Error if used in a same scope
    • But still can use both namespaces
    • Must specify which namespace is used at what time

Using Declarations

  • using NAME_SPACE::ONE_NAME;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
namespace NS1 {
    void myFunction() {
        cout<<"foo_ns1"<<endl;
    }
    void fun1() {
        cout<<"foo1"<<endl;
    }
 }
 namespace NS2 {
    void myFunction() {
        cout<<"foo_ns2"<<endl;
    }
    void fun2() {
        cout<<"foo2"<<endl;
    }
}

int main() {
	{
		using NS1::fun1;
		using NS2::fun2;
		fun1();
		fun2();
	}
	{
		using NS1::myFunction;
		using NS2::myFunction; 
		myFunction();//ILLEGAL
	}
	{
		using namespace NS1;
		using namespace NS2;
		//Legal but..
		myFunction(); //ILLEGAL
		NS1::myFunction(); //Legal
	}
}

Qualifying names

  • Specify where name comes from with qualifier and scope-resolution operator
  • Used if you only intend to use one time

Unnamed Namespaces

  • Compilation unit : A file along with all files that are #includeded in the file, such as interface header file
  • Every compilation unit has an unnamed namespace
  • Unnamed namespace enables using functions without qualifications within the compilation unit

Nested Namespaces

  • Legal to nest namespaces
1
2
3
4
5
6
7
8
9
10
namespace S1
{
	namespace S2
	{
	void sample() {}
	}
}

S1::S2::sample(); 
//Qualify names twice
  • Namespace defininitions are placed inside namespace groupings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace NS{
	void myFunction();
}
namespace NS{
	void myFunction() {
		some defs..
	}
}

int main() {
	NS::myFunction();
	using namespace NS;
	myFunction();
	using NS::myFunction;
	myFunction();
}

RAII

  • Resource Acquisition is Initialization
  • Principle : a resource’s lifetime = an object’s lifetime
    • Acquisiation (Initialization) : Acquire resource (allocate memory, open a file) inside the constructor of an obj
    • Release(Destruction) : You automatically release that resource inside the destructor of the same object

Without RAII

  • Manuel management
1
2
3
4
5
6
void process(bool fail) {
	File* f = newFile("data.txt");
	if (fail) return;
	delete f;
}
// if Fails, never deletes f
  • Every path must rememeber to delete
  • Early retrun / exception makes silent leak
  • unique_ptr
1
2
3
4
5
void process(bool fail) {
	auto f = make_unique<File>("data.txt");
	if (fail) return;
}
// No explicit delete but destructor frees it
  • No delete anywhere
  • Same behavior, zero chance of a leak

Smart Pointer

  • unique_ptr : one exclusive owner
  • shared_ptr : shared, reference-counted
  • weak_ptr: non-owning observer

unique_ptr

  • Exactly one owner at a time
    • Move-only : copying is disabled
    • Transfer with std::move
  • Freed automatically when it dies
  • Zero overhead versus a raw pointer
1
2
3
4
std::unique_ptr<T> uptr = std::make_unique<T>()
//Make unique_ptr of type T
auto anotherPtr = std::move(uptr);
if (uptr == nullptr) //True

Rule of Zero

  • build from self-managing memebers
  • The compiler generates the rest correctly
This post is licensed under CC BY 4.0 by the author.