Presentation is loading. Please wait.

Presentation is loading. Please wait.

SNU OOPSLA Lab. Chap8. Namespaces and Exceptions © copyright 2001 SNU OOPSLA Lab.

Similar presentations


Presentation on theme: "SNU OOPSLA Lab. Chap8. Namespaces and Exceptions © copyright 2001 SNU OOPSLA Lab."— Presentation transcript:

1 SNU OOPSLA Lab. Chap8. Namespaces and Exceptions © copyright 2001 SNU OOPSLA Lab.

2 SNU OOPSLA Lab. C++ Contents Modularization and Interfaces Namespaces Exceptions

3 SNU OOPSLA Lab. C++ 1. Modularization and Interfaces The desk calculator example(6.1) is composed of five parts The parser, doing syntax analysis The lexer, composing tokens out of characters The symbol table, holding (string,value) pairs The driver, main( ) The error handler

4 1. Modularization and Interfaces driver parser lexer symbol table error handler “using” just interface

5 SNU OOPSLA Lab. C++ 1. Modularization and Interfaces When breaking up a program into modules, take care to minimize dependencies between modules

6 SNU OOPSLA Lab. C++ 2. Namespaces How to represent modules as namespaces A mechanism for expressing logical grouping ex> the declarations of the parser from the desk calculator(6.1) may be placed in a namespace Parser Namespace Parser{ double prim(bool); double term(bool); double expr(bool); } double Parser::prim(bool get){/*…*/} double Parser::term(bool get){/*…*/} double Parser::expr(bool get){/*…*/}

7 SNU OOPSLA Lab. C++ 2. Namespaces Members of a namespace namespace namespace-name{ //declaration and definitions } or namespace namespace-name{ //declaration } namespace-name::member-name//definition

8 SNU OOPSLA Lab. C++ 2.1 Qualified Names A namespace is a scope, so the usual scope rules hold for namespaces A name from another namespace can be used by the name of its namespace double Parser::term(bool get) //note Parser::qualification {double left = prim(get); //no qualification needed for( ; ; ) switch(Lexer::curr_tok) { //note Lexer::qualification case Lexer::MUL: //note Lexer::qualification left *= prim(true); //no qualification needed }

9 2.2 Using Declarations The repeated qualification outside its namespace is tedious and distracting=> using-declaration Double Parser::prim(bool get) { if (get) Lexer::get_token(); switch(Lexer::curr_tok){ case Lexer::NUMBER:://… caseLexer::NAME://… //… default: return Error::error (“primary expected”); } Double Parse::prim(bool get) { using Lexer::get_token; using Lexer::curr_tok; using Error::error; if (get) get_token(); switch(curr_tok){ case Lexer::NUMBER:://… //… default: return error(“primary expected”); }

10 SNU OOPSLA Lab. C++ 2.3 Using Directives How to simplify the Parser functions to be exactly our original versions? using-directive Namespace Parser{ double prim(bool); double term(bool); double expr(bool); using namespace Lexer;//make all names from Lexer available using namespace Error;//make all names from Error available } double Parser::term(bool get) {// write Parser’s original functions }

11 SNU OOPSLA Lab. C++ 2.4 Multiple Interfaces namespace Parser{ double expr(bool); } namespace Parser{ double prim(bool); double term(bool); double expr(bool); using Lexer::get_token;//use Lexer’s get_token using Lexer::curr_tok;//use Lexer’s curr_tok using Error::error;//use Error’s error } Interface for users Interface for implementers

12 SNU OOPSLA Lab. C++ 2.4 Multiple Interfaces Driver Parser implementation Parser’Parser Parser’ small interface for users Parser interface for implementers Don’t need to use two separate namespaces

13 SNU OOPSLA Lab. C++ 2.4.1 Interface Design Alternatives Minimal interface easier to understand, better data hiding properties, easier to modify, compile faster The aim make the set of potential dependencies reduced to the set of actual dependencies

14 SNU OOPSLA Lab. C++ 2.4.1 Interface Design Alternatives namespace Parser{ //interface for implementers //… double expr(bool); //… } int main() { //… Parser::expr(false); //… } main() depends on Parser::expr()

15 2.4.1 Interface Design Alternatives namespace Parser{ //interface for implementers //… double expr(bool); //… } namespace Parser_interface{ //interface for users using Parser::expr; } namespace Parser{ //interface for users //… double expr(bool); //… } namespace Parser_interface{ //separately named interface for users using Parser::expr; } Driver Parser implementation Driver Parser implementation Parser_interface Parser Parser_interface Parser’

16 SNU OOPSLA Lab. C++ 2.4.1 Interface Design Alternatives Minimized dependency namespace Parser_interface{ double expr(bool); } double Parser_interface::expr(bool get) { return Parser::expr(get); } Driver Parser implementation Parser_interface implementation Parser_interfaceParser

17 SNU OOPSLA Lab. C++ 2.5 Avoiding Name Clashes Ex> name clash //my.h: char f(char); int f(int); class String{/* …*/}; //your.h; char f(char); double f(double); class String{/*…*/}; namespace My{ char f(char); int f(int); class String{/* …*/}; } namespace Your{ char f(char); double f(double); class String{/*…*/}; } solution

18 SNU OOPSLA Lab. C++ 2.5.1 Unnamed Namespaces The namespace without a name How to access members of an unnamed namespace from the outside an unnamed namespace has an implied using-directive namespace{ int a; void f(){/*…*/} int g(){/*…*/} } namespace $$${ int a; void f(){/*…*/} int g(){/*…*/} } using namespace $$$;

19 SNU OOPSLA Lab. C++ 2.6 Name Lookup If a function isn’t found in the context of its use, we look in the namespaces of its arguments This lookup is useful for operator operands and template arguments void f(Chrono::Date d, std::string s) { if(d==s){ //… } else if(d==“august 4, 1914”){ //… } std::operator==() doesn’t take a Date argument, so Chrono::operator==()

20 SNU OOPSLA Lab. C++ 2.7 Namespace Aliases Solution : short alias for a longer namespace name namespace A{…} A::String s1=“Grieg”; A::Strings2=“Nielsen”; namespace American_Telephone_and_Telegraph{…} American_Telephone_and_Telegraph::String s3=“Grieg”; American_Telephone_and_Telegraph::String s4=“Nielsen”; short name, will clash too long namespace ATT=American_Telephone_and_Telegraph; ATT::String s3=“Grieg”; ATT::String s4=“Nielsen”;

21 SNU OOPSLA Lab. C++ 2.8 Namespace Composition Compose an interface out of existing interfaces namespace His_string{ class String{…}; void fill(char); } namespace Her_vector{ template class Vector{…}; } namespace My_lib{ using namespace His_string; using namespace Her_vector; void my_fct(String&); } void f() { My_lib::String s=“Byron”; } using namespace My_lib; void g(Vector & vs) { my_fct(vs[5]); } Only if define something, need to know the real namespace of an entity void My_lib::fill(){…}//error : no fill() declared in My_lib void His_string::fill(){…}//ok:fill() declared in His_string

22 SNU OOPSLA Lab. C++ 2.8 Namespace Composition Ideally a namespace should express a logically coherent set of features not give users access to unrelated features no impose a significant notational burden on users

23 SNU OOPSLA Lab. C++ 2.8.1 Selection Selection of features from a namespace using-declaration namespace My_string{ using His_string::String; using His_string::operator+; }

24 SNU OOPSLA Lab. C++ 2.8.2 Composition and Selection namespace His_lib{ class String{…}; template class Vector{…}; } namespace Her_lib{ template class Vector{…}; class String{…}; } namespace My_lib{ using namespace His_lib; using namespace Her_lib; using His_lib::String; using Her_lib::Vector; template class List{…}; } namespace Lib2{ using namespace His_lib; using namespace Her_lib; using His_lib::String; using Her_lib::Vector; typedef Her_lib::String Her_string; template class His_vector :public His_ilb::Vector {…}; template class List{…}; } additional stuff Names explicitly declared in a namespace take priority over names made accessible in another scope by using-directive resolve clash in favor o f His_lib resolve clash in favor o f Her_lib rename “rename” additional stuff

25 SNU OOPSLA Lab. C++ 2.9.1 Namespaces and C Redesign existing code Make it relatively easy to take a program written without namespaces and turn it into a more explicitly structured one using namespace => using-directive //stdio.h: namespace std{ int printf(const char*…); } using namespace std; //cstdio: namespace std{ int printf(const char*…); } //stdio.h: include using namespace std; for people who don’t want the names implicitly available

26 SNU OOPSLA Lab. C++ 2.9.2 Namespaces and Overloading Overloading works across namespaces //old A.h: void f(int); //old B.h: void f(char); //old user.c: #include “A.h” #include “B.h” void g() { f(‘a’); //calls the f() from B.h } //new A.h: namespace A{ void f(int); } //new B.h: namespace B{ void f(char); } //new user.c: #include “A.h” #include “B.h” using namespace A; using namespace B; void g() { f(‘a’); //calls the f() from B.h }

27 SNU OOPSLA Lab. C++ 2.9.3 Namespaces Are Open Can add names to a namespace from several namespace declaration Allows us to present different interfaces to different kinds of users by presenting different parts of a namespace namespace A{ int f();//now A has member f() } namespace A{ int g();//now A has two members, f() and g() }

28 SNU OOPSLA Lab. C++ 3. Exceptions In module programming, two parts of error handling The reporting of error conditions not resolved locally The handling of errors detected elsewhere Exceptions are C++means of separating error reporting from error handling

29 SNU OOPSLA Lab. C++ 3.1 Throw and Catch The notion of an exception is provided to help deal with error reporting struct Range_error{ int I; Range_error(int ii){I=ii;} }; char to_char(int I) { char c=I&static_cast (-1); if(I!=c) throw Range_error(I); return c; } void h( int I) {try{ char c=to_char(I); } catch(Range_error x){ cerr<<“oops:to_char(“<<x.I<<“)\n”; } exception handlier throw an exception

30 SNU OOPSLA Lab. C++ 3.2 Discrimination of Exceptions Several different possible run-time errors in a program Map into exception with distinct names Ex> 2 error in calculator(6.1) syntax errors attempts to divide by zero try{ expr(false); } catch(Syntax_error) { //handle syntax error } catch(Zero_divide){ //handle divide by zero }

31 SNU OOPSLA Lab. C++ 3.2 Discrimination of Exceptions try{ } catch(input_overflow){ thrown input_overflow(); } Any exceptions thrown while executing a handler must be dealt with by the callers of the try-block Exception handlers can be nested try{ } catch(XXII){ try{ } catch(XXII){ }

32 SNU OOPSLA Lab. C++ 3.3 Exceptions in the Calculator Rework the calculator example(6.1) to separate the handling of errors from the main logic of it The parser eliminate error() detect three syntax errors return error(“divide by 0”); return error(“) expected”); return error(“primary expected”); return error(“divide by 0”); throw Error::Syntax_error(“divide by 0”); throw Error::Syntax_error(“’)’ expected”); throw Error::Syntax_error(“primary expected”); throw Error::Zero_divide();

33 SNU OOPSLA Lab. C++ 3.3 Exceptions in the Calculator The driver handle Zero_divide and Syntax_error int main(int argc, char* argv[]) { while(cin){ try { Lexer::get_token(); //… } catch(Error::Zero_divide){//… skip(); } catch(Error::Syntax_error e){//… skip(); } namespace Driver{ int no_of_errors; std::istream* input; void skip(); } void Driver::skip() { using std::cin; no_of_errors++; while(cin){ //… switch(ch){ case ‘\n’: case ‘;’: cin.get(ch); return; } skip tokens until EOL or ;

34 Bad for a several reasons: State variables are a common source of confusion and errors Good strategy to keep error handling and “normal” code separate Doing error handling using the same level of abstraction as the code that caused that the error is hazardous To add error-handling code rather than separate error-handing routines int main(int argc, char* argv[]) { bool in_error = false; while (cin){ try{ Lexer::get_token(); //… if (in_error==false) cout<<Parse::expr(false)<<‘\n’; } catch(Error::Zero_divide){ cerr<<“attempt to divide by zero\n”; in_error=ture; } catch(Error::Syntax_error e){ cerr<<“syntax error:”<<e.p<<“\n”; in_error=true; }


Download ppt "SNU OOPSLA Lab. Chap8. Namespaces and Exceptions © copyright 2001 SNU OOPSLA Lab."

Similar presentations


Ads by Google