350 likes | 464 Views
Name lookup (name control). Variables Variable names are searched for in the below order. 1. Locally 2. Class-scope 3. File scope (global). Name lookup (name control). void fun(int x) { { int x = 5; cout << x << endl; } cout << x << endl; }.
E N D
Name lookup (name control) • Variables • Variable names are searched for in the below order. 1. Locally 2. Class-scope 3. File scope (global)
Name lookup (name control) void fun(int x) { { int x = 5; cout << x << endl; } cout << x << endl; }
Name lookup (name control) • Functions • Name to match a function is searched for in the below order. 1. Class-scope (if invoked from an operation belonging to a class) 2. File-scope
Name lookup (name control) • Example class-scope void X::fun() { f(); } class X { //. . . void f(); // name match }; • The scope operator :: makes it possible to access the desired scope
Name lookup (name control) • The search for a name match is always done before the access control. void f(){. . .} //global function class X : public B {. . .}; class B { //. . . private: void f(); // name match }; void X::fun(){ f(); }
Class scope (name control) • Enumerations, shared data, and functions class Date { public: enum Weekday { MON, TUE, WED, THU, FRI, SAT, SUN }; static int days_per_month[12]; //shared data static bool is_leap(int); //shared function //. . . }
Class scope (name control) • Declaration of an array with constant size in a class class Stack { //. . . private: static const int SIZE = 20; // new proposed feature, still an ERROR with most compilers static const int SIZE; // OK, but this still does not help array initialization enum { SIZE = 20 }; // This is the trick int array[SIZE]; } const int Stack :: SIZE = 20; //implementation //initialization
Namespaces (name control) //Declarations namespace Vendor_A_Containers { template<class T> class List { . . . }; template<class T> class Queue { . . . }; . . . } //Implementation namespace Vendor_A_Containers { template<class T> T Queue<T>::remove() { . . . }; template<class T> int Queue<T>::length() const { . . . }; . . . }
Namespaces (name control) • Using namespaces //Method 1 //exhaustive Vendor_A_Containers::Queue<Employee> q; //The programmer defines an alias. namespace Cont = Vendor_A_Containers; Cont::Queue<Employee> q; //BETTER!
Namespaces (name control) Method nr 2 class Bank { using Vendor_A_Containers :: Queue; // . . . private: Queue<Customer> waitingQueue; . . . }; • A using declaration can be put into any scope
Namespaces (name control) #include <stdlib.h> //deprecated • To provide backward compatibility with the C standard library, the <xxx.h> naming is still supported, although it is deprecated. • Use the newer <cxxx>, or <xxx> instead. #include <cstdlib> //OK • The <cxxx> is used for the old c-headers and the <xxx> is used for the c++-headers.
An example //Namespace.h #ifndef _RS_NAMESPACE_ #define _RS_NAMESPACE_ namespace RS_namespace { template <class T> class List { template <class T> class Nod; public: typedef Nod<T> nod; typedef Nod* nod_ptr; List(); ~List(); void ListInsert(T); //. . . private: template <class T> class Nod { public: T data; Nod<T>* next; }; nod_ptr head; int size; }; } //end RS_namespace #endif
//List.cpp #include "RS_namespace.h" namespace RS_namespace { //pre: none //post:a list object is created and initiated template <class T> List<T>::List() { size=0; //sätter storlek på listan till 0 head=NULL; } //pre: none //post:The list object is removed, and memory is returned template <class T> List<T>::~List() { while (!ListIsEmpty()) ListDelete(1); } //pre: none //post:An element is inserted as the first element of the list template <class T> void List<T>::ListInsert(T newdata) { size++; nod_ptr newptr=new Nod; newptr->data=newdata; newptr->next=head; //sätt alltid in först i listan head=newptr; } } //end namespace
//main.cpp #include "RS_namespace.h" void main() { //using just List from RS_namespace using RS_namespace::List; //Induce the whole namespace ”RS_namespace” using namespace RS_namespace; List<int> myList; }
Access control (name control) • Declarations and definitions • Example definitions int x; Employee lars("Lars"); int square(int x){ return x*x; } • Example declarations extern int x; extern Employee lars; int square(); class Date; enum Color;
Access control (name control) • Public, private and protected • public • Access is allowed from all clients. • protected • Access is allowed from the class itself, subclasses and friends. • Private • Access is allowed from the class itself and friends.
Access control (name control) • Friends - (use with care) • A class can declare a function or another class as a friend. This gives the declared friend(s) total access to the class members. class Link { friend class List; friend class Queue; private: Link() : _next=0 {}; int _info; Link* _next; }; • When is this useful?
Access control • Friends (cont...) • The friend keyword is not only telling you that this function is a friend it is also implicitly telling you that it is not a member. • The friend keyword can only be used within a class-definition.
Design issues for name control • Don’t pollute the global namespace with global variables. • Eliminate them by making them shared data members of a class. • Eliminate global functions by making them shared class functions. • Use a nested class to define a class that are implementation specific to the class that use it • Think carefully before taking a decision about making a function or class a friend. • Do not use protected data!
Objects • An object is characterized by its: • State • Operations • Identity • What is a class? • What is object oriented programming?
Memory handling • A C++ program can allocate memory in three memory areas: • The run time stack (Automatic storage) • Static storage • The heap memory, also called free storage or dynamic memory.
Constructors (memory handling) • Every class has four special member functions: • The default constructor • The copy-constructor • The destructor • The assignment operator
Generation of default cons. class File { private: string path; int mode; public: File(const string& file_path, int open_mode); ~File(); }; //error, array requires default //constructorFile File folder1[10]; // error, f2[1] still requires // default constructor File folder2[2] = { File("f1", 1)}; //OK, fully nitialized array folder3[3] = { File("f1", 1), File("f2",2), File("f3",3) };
Explicit constructors class string { public: string(); //constructors and implicit //conversion operators string(int size); string(const char *); ~string(); private: int size; int capacity; char *buff; };
Explicit constructors • What happens in the program below? int main() { string s = "hello"; //OK, convert a //C-string into a string object int ns = 0; s = 1; // 1 oops, programmer //intended to write ns = 1 }
Explicit constructors • Solution class string { public: //block implicit conversion explicit string(int size); //implicit conversion string(const char *); ~string(); };
Explicit constructors • Solution (cont..) int main() { string s = "hello"; //OK, convert a //C-string into a string object int ns = 0; s = 1; // compile time error, this //time the compiler catches //the typo }
Initializing class members • There are four different cases to consider when initializing class members in the constructor. • Initialization of const members. • Initialization of alias (reference) members. • Initialization of base class members through a subclass, by sending arguments to the base class constructor. • Initialization of member objects. • In the three first cases an initializer list is mandatory. The fourth case is optional.
Copy constructors • Why have one? • To copy objects who differ only in identity. • To copy arguments and return values to and from functions, using call-by-value. • When do you absolutely need to define one? • All classes with a non trivial destructor need both a user defined copy-constructor and a user defined assignment operator.
Destructors • Why have a destructor? • To free resources. • When do I have to define it explicitly? • Whenever there is dynamic memory allocation involved. • Why have a virtual destructor? • Whenever the class is a potential base class.
The assignment operator • Why have one? • To be able to control what happens when assignment takes place. • When do I need to define one? • All classes with a non trivial destructor need a user defined assignment operator. • Generic form C& C::operator=(const C&);
The assignment operator • The assigment operator and the destructor. // What happens? List a: a.insert(. . .); //. . . List b; b.insert(. . .); //. . . a = b; // b goes out of scope
The assignment operator Two problems: The list a is not removed. The list b is removed twice!
Common factors ... • … between the destructor, the copy constructor and the assignment operator void List::copy(const List& b) { //kod för att kopiera } void List::free() { //kod för att frigöra minnet } List::List(const List& b) { copy(b); }
Common factors . . . List::~List() { free(); } const List& List::operator=( const List& b ) { if( this != &b) { free(); copy(b); } return *this; }