NULL
is the null pointer;
NUL
is the ASCII NUL character (zero byte), also represented in C as
'\0'
current_node
that we pick may or may not be a successor of the previous
current_node
reduce_key()
operation if using a priority queue
this
pointer
class Abstract1 {
public:
virtual void crawl =0;
virtual int walk() = 0;
};
class Abstract2 {
public:
virtual void crawl() {
cout << "you have to crawl before you can " << walk() << "\n";
}
};
class Concrete: public Abstract2 {
public:
virtual int walk() {return 42;}
};
Concrete thing;
thing.crawl();
virtual
A substantial part of programming is about resource management. Resources include memory, open files, mutexes, etc.
It is important to be careful to note who owns an object in the documentation. Since this is an agreement between the library provider and library client, it is known as a contract. For example:
class Edge {
public:
//...
// Returns pointer to the from edge.
// Valid as long as Graph is valid.
Vertex* GetFrom();
private:
//...
Vertex* from_'
};
// Allocate new vertex. Client is responsible for deleting.
Vertex* VertexFactory(const string& label);
C++ introduced constructors and destructors. The constructor ensures that an object is well-formed (all fields properly initialized). The destructor performs any required clean up.
For function-local objects, the destructor is called automatically when the code leave its scope. Destructors are called in reverse order of construction.
Resources may be managed using the constructor and destructor. This style of programming is known as RAII
For objects allocated on the heap (i.e. returned by
new
),
the programmer is responsible for explicitly calling
delete
delete
on anything other than a value returned by
new
Constructor: initialize base object, initialize members (in declaration order), then call constructor code:
#include <iostream>
#include <string>
using namespace std;
class Base {
public:
Base(const string& s) : s_(s) {cout << "Base(" << s_ << ")\n";}
~Base() {cout << "~Base(" << s_ << ")\n";}
private:
string s_;
};
class Member {
public:
Member(const string& s) : s_(s) {cout << "Member(" << s_ << ")\n";}
~Member() {cout << "~Member(" << s_ << ")\n";}
private:
string s_;
};
class Derived : public Base {
public:
Derived(const string& s) :
member2_("member 2"),
s_(s),
Base("base"),
member1_("member 1")
// Better style would be to initialize members in the order they occur:
// member1_("member 1"), member2_("member 2"), s_(s)
// since that's the order they're initialized
{
cout << "Derived(" << s_ << ")\n";
}
~Derived() {cout << "~Derived(" << s_ << ")\n";}
private:
string s_;
Member member1_;
Member member2_;
};
int main() {
Derived d("derived object");
return 0;
}
Base(base)
Member(member 1)
Member(member 2)
Derived(derived object)
~Derived(derived object)
~Member(member 2)
~Member(member 1)
~Base(base)
Some languages, e.g. Java, implement garbage collection but it is not a panacea. Other languages, e.g. Python, use reference counting, also not a panacea.
C++ comes from C which was designed to work with low overhead on smaller systems, hence manual memory management.
Understanding manual memory management helps the software engineer avoid hitting the pitfalls of automatic memory management.
The destructor is used to ensure that resources are released.
smart pointers... operator overloading