Download presentation
Presentation is loading. Please wait.
1
2.1 Program Defects and "Bugs
2.2 Exceptions 11 – Program Correctness
2
Attendance Quiz #9 Program Correctness
3
Tip #11: Virtual Functions
Program Correctness Polymorphism refers to the ability to associate many meanings to one function name by means of a special mechanism known as virtual functions or late binding. There are clear advantages to using virtual functions, so, why not make all member functions virtual? The answer: There is a large overhead to making a function virtual. class Instrument virtual void play() {} class Wind : public Instrument class Percussion : public Instrument ... vector<Instrument*> instruments; instruments.push_back(new Wind()); instruments.push_back(new Percussion()); for (size_t i; i < instruments.size(); ++i) instruments[i]->play(); It uses more storage and makes your program run slower than if the function were not virtual. That is why the designers of C++ gave the programmer control over which member functions are virtual and which are not. If you expect to need the advantages of a virtual member function, then by all means, make that member function virtual. If you do not expect to need the advantages of a virtual function, then your program will run more efficiently if you do not make the member function virtual.
4
Follow-up… Program Correctness #include <iostream>
#include <vector> #include <string> #include "shape.h" #include "cube.h" #include "pyramid.h" using namespace std; int main(int argc, char* argv[]) { vector<Shape*> shapes; shapes.push_back(new Shape("Shape")); shapes.push_back(new Cube("Cube")); shapes.push_back(new Pyramid("Pyramid")); for (int i = 0; i < shapes.size(); i++) cout << shapes[i]->toString() << endl; //cout << shapes[i]->getSides() << endl; } Cube *cube2 = new Cube("Cube 2"); cout << cube2->getSides() << endl; Shape cube3("Cube 3"); //cout << cube3.getSides() << endl; return 0; #ifndef CUBE_H #define CUBE_H #include <string> #include <sstream> #include "shape.h" using namespace std; class Cube : public Shape { private: int sides; public: Cube(const string& name) : Shape(name), sides(6) {} int getSides() { return sides; } string Cube::toString() const ostringstream sb; sb << Shape::toString(); return sb.str(); } }; #endif #ifndef SHAPE_H_ #define SHAPE_H_ #include <string> using namespace std; class Shape { private: std::string name; public: Shape(const string& name) : name(name) {} string getName() const { return name; } string toString() const ostringstream sb; sb << "Shape: " << name; return sb.str(); } }; #endif
5
The friend Declaration
Inheritance #include <iostream> using namespace std; class Box { private: double width; public: friend void printWidth(Box box); void setWidth(double wid) { width = wid; } }; void printWidth(Box box) cout << "Width of box = " << box.width << endl; } // Main function for the program int main() Box box; box.setWidth(10.0); printWidth(box); return 0; printWidth() is not a member function of any class. Use friend function to print the wdith – can directly access any member of box.
6
SNAP UML Iterators Student Course SNAP Csg Cdh Cr -int studID
+int getStudID() +toString() const Course -string course +string getCourse() +toString() const SNAP -int studID -string name -string address -string phone +int getStudID() +string getName() +string getAddr() +string getPhone() +toString() const Csg -string course -int studID -string grade +string getCourse() +int getStudID() +string getGrade() +toString() const Cdh -string course -string day -string hour +string getCourse() +string getDay() +string getHour() +toString() const Cr -string course -string room +string getCourse() +string getRoom() +toString() const
7
SNAP UML Iterators Student Csg Course Cr Cdh SNAP -int studID
+int getStudID() +toString() const Csg -string course -int studID -string grade +string getCourse() +int getStudID() +string getGrade() +toString() const Course Cr -string course -string room +string getCourse() +string getRoom() +toString() const Cdh -string course -string day -string hour +string getCourse() +string getDay() +string getHour() +toString() const SNAP -int studID -string name -string address -string phone +int getStudID() +string getName() +string getAddr() +string getPhone() +toString() const
8
2.1 Program Defects and "Bugs''
Syntax Errors Run-time Errors Logic Errors 2.1, pgs
9
Program Defects and "Bugs"
Program Correctness The term "bug" refers to a software defect. Debugging is a commonly used term for removing defects. Easier to eliminate defects by careful design than through testing. Testing is used to show that a program is correct, but it is difficult to determine how much testing needs to be done. testing can never demonstrate the complete absence of defects. complete testing in some environments (missile control software, nuclear power plant controls) is very difficult. You may encounter three kinds of defects or errors: Syntax errors, Run-time errors or exceptions, Logic errors.
10
Syntax Errors Program Correctness Syntax errors are mistakes in using the grammar (syntax) of the C++ language. The C++ compiler will detect most syntax errors during compilation. Some common syntax errors: Omitting or misplacing braces that bracket compound statements. Invoking a member function that is not defined for the object to which it is applied. Not declaring a variable before using it. Providing multiple declarations of a variable. Not assigning a value to a local variable before referencing it. Not returning a value from a function whose result type is not void. Unfortunately, the compiler may not detect syntax errors that are the result of typographical errors, such as using = when you intended to use ==.
11
Run-time Errors Program Correctness Run-time errors occur during program execution when the computer or the C++ run-time library detects an operation that it knows to be incorrect. Most run-time errors cause the operating system or run-time library to issue an error message and halt the program. Different computers, operating systems, and compilers handle these errors differently. Some common run-time errors include:
12
Logic Errors A logic error occurs when the programmer or analyst
Program Correctness A logic error occurs when the programmer or analyst makes a mistake in the design of a class. makes a mistake in the design of a class function. has implemented an algorithm incorrectly. uses an incorrect algorithm. The C++ code will compile and run, but will not meet the specifications—it will produce incorrect results. Most logic errors do not cause syntax or run-time errors and, consequently, are difficult to find. Test cases can help find logic errors. Test cases allow the programmer to compare actual program output with the expected results. Software professionals must be diligent in detecting and correcting logic errors.
13
Logic Error Results Program Correctness The original Mars Lander spacecraft crashed because of inconsistent calculations (feet versus meters). Billing programs have sent out bills for exorbitant amounts of money. ATM programs and off-track betting programs have caused machine owners to lose significant amounts of money. Many popular operating systems have been released with bugs that have allowed hackers to access computers easily and illicitly. A popular word processor when integrated with a document management system "ate" documents off the server leaving an empty file. In the 1980s several patients died after software controlling therapeutic radiation machines gave them massive overdoses. In August 2004, two automobile recalls that could have led to fatal accidents occurred because of software errors in control systems.
14
Quiz: Identify any syntax, run-time, and/or logic errors:
#include <iostream> int findMax(int a[], n) { int max = std::numeric_limits<int>::max(); for (int i = 0; i <= n; i++) if (a[i] > max) max = a[i]; } return max; int main(int argc, char* argv) cout << "Program: " << argv[0] << endl; int a[] = { 7, 5, 3, 10, 2, 6 } cout << "findMax(a) = " << findMax(a, 6); return 0;
15
Quiz: Identify any syntax, run-time, and/or logic errors:
#include <iostream> int findMax(int a[], n) { int max = std::numeric_limits<int>::max(); for (int i = 0; i <= n; i++) if (a[i] > max) max = a[i]; } return max; int main(int argc, char* argv) cout << "Program: " << argv[0] << endl; int a[] = { 7, 5, 3, 10, 2, 6 } cout << "findMax(a) = " << findMax(a, 6); return 0; Syntax Syntax Run-time Logic Run-time Syntax Syntax
16
3.5, pgs. 213-217 2.2 Exceptions Ways to Indicate an Error
The throw Statement Uncaught Exceptions Catching and Handling Exceptions with try and catch Blocks Standard Exceptions The Exception Class Hierarchy Catching All Exceptions 3.5, pgs
17
To Error is Human What to do with an error:
Program Correctness What to do with an error: Return a special value. Use a bool return value to indicate success or failure. Set a global variable. Print an error message. Print an error message and exit the program. Put an input or output stream in a fail state. The first three options allow the user of a function to respond to the error. To err is human… But to really screw up, you need a computer!
18
Exceptions Program Correctness An alternate way to indicate an error, especially if there are several possible errors, is through the use of exceptions. Exceptions are used to signal that an error has occurred during the execution of a program. You can insert code in your program that throws an exception when a particular kind of error occurs. When an exception is thrown, the normal flow of execution is interrupted and control transfers to another part of the program. An exception handler allows the user to catch or handle the exception.
19
Exception Handling The exception object can be of any type.
Program Correctness The exception object can be of any type. The standard library includes standard exception classes. User defined exceptions can be of any data type. If an exception occurs and is not caught, the program stops and an error message is displayed. To avoid uncaught exceptions you write a try block that can throw an exception and follow it with a catch block that catches the exception and handles it. Code within a try/catch block is referred to as protected code. More than one catch block can follow a try block. Each catch block handles a different kind of exception. They are checked in the order in which they appear.
20
try-catch Blocks Program Correctness try { age = read_int("Enter your age: "); } catch (std::ios_base::failure& f) cerr << "Invalid number format input" << endl; age = DEFAULT_AGE; catch (std::exception& ex) cerr << "Fatal error: " << ex.what() << endl; abort(); catch (...) cerr << "Undefined exception in read_int" << endl; If all statements in the try block execute without error, the exception handler (the catch block) is skipped
21
When To Use try-catch Blocks
Program Correctness When an error event happens routinely and could be considered part of normal execution, handle without throwing exceptions. Use try-catch blocks Around code that can potentially (and unexpectedly) generate an exception. Prevent and recover from application crashes. Throw an exception when your program can identify an external problem that prevents execution. Compared to error reporting via return-codes and if statements, using try / catch / throw is likely to result in code that has fewer bugs, is less expensive to develop, and has faster time-to-market. Constructors and Destructors Constructors don't have a return type, so it's not possible to use return codes, therefore to throw an exception. Destructors should never throw an exception because of stack unwinding.
22
Standard Exceptions Exception Source bad_alloc bad_cast bad_typeid
Program Correctness Exception Source bad_alloc Thrown by new. bad_cast Thrown by dynamic_cast. bad_typeid Thrown by typeid. domain_error Thrown when a mathematically invalid domain is used. length_error Thrown when a too big std::string is created. invalid_argument Thrown due to invalid arguments. out_of_range Thrown by the 'at' method. io_base::failure Thrown by I/O stream objects after erroneous I/O operations. runtime_error Exception that theoretically cannot be detected by reading the code. range_error when you try to store a value which is out of range. overflow_error Thrown if a mathematical overflow occurs. underflow_error Thrown if a mathematical underflow occurs. … Catch all throws
23
Vector Example animals.at() throws an exception. animals[ ] does not!
Program Correctness #include <iostream> #include <vector> #include <string> #include <stdexcept> using namespace std; int main(int aargc, char* argv[]) { vector<string> animals = { "dog", "cat", "horse" }; try for (int i = 0; i < 4; i++) //cout << animals[i] << endl; cout << animals.at(i) << endl; } catch (std::out_of_range& oor) { cerr << oor.what() << endl; } // catch anything thrown within try block that derives from std::exception catch (const std::exception &exc) { cerr << exc.what() << endl; } // catch everything, but can't do anything w/exception. catch (...) { cerr << "???" << endl; } return 0; animals.at() throws an exception. animals[ ] does not!
24
Define Your Own Program Correctness You can define your own exceptions by inheriting and overriding exception class functionality. #include <iostream> #include <exception> using namespace std; struct MyException : public exception { const char* what() const throw() return "C++ Exception"; } }; int main() try throw MyException(); catch(MyException& e) cout << "MyException caught " << e.what() << endl; catch(exception& e) { cout << e.what() << endl; } //Other errors what() is a public method provided by exception class and it has been overridden by all the child exception classes. This returns the cause of an exception.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.