Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Abstract Data Types Chapter 1. 2 Objectives You will be able to: 1. Say what an abstract data type is. 2. Implement a simple abstract data type in C++

Similar presentations


Presentation on theme: "1 Abstract Data Types Chapter 1. 2 Objectives You will be able to: 1. Say what an abstract data type is. 2. Implement a simple abstract data type in C++"— Presentation transcript:

1 1 Abstract Data Types Chapter 1

2 2 Objectives You will be able to: 1. Say what an abstract data type is. 2. Implement a simple abstract data type in C++

3 3 Abstract Data Type As we study data structures, we will usually implement them as abstract data types. A set of data values and associated operations that are precisely specified independent of any particular implementation. A concept, not software. We implement abstract data types as modules of software. In C++, the modules are classes.

4 4 Abstract Data Type Not all classes implement abstract data types. If a class does implement an abstract data type, programmers typically say that it is an abstract data type. But there can be many different implementations of a given abstract data type. The duck test

5 5 Example: Class Circle class Circle { private: double radius; char name[20]; public: // Constructor Circle(const char* name_, double radius_); // Return the radius of this circle. double Get_Radius(); // Return the name of this circle. char* Get_Name(); // Return the area of this circle. double Get_Area(); }; File Circle.h

6 6 Download File Circle.h is available in the Downloads area of the class web site: Delete the.txt extension if you want to download and compile the program. You can view the file by clicking on the name in a browser. If you want to compile the program in Visual Studio, create a project for it.

7 7 Creating New Project

8 8

9 9

10 10 Creating New Project

11 11 We have a project.

12 12 Download into Project Directory

13 13 Download into Project Directory Download all three files the same way, omitting the.txt

14 14 Add files to the project The files are in the project directory but they are not in the project. We have to add them to the project.

15 15 Add files to the project

16 16 Add files to the project

17 17 The files are now in the project

18 18 Circle.h in Editor

19 19 Implementing Member Functions #include #include "Circle.h" Circle::Circle(const char* name_, double radius_) { assert(radius_ >= 0.0); radius = radius_; strncpy(name, name_, 19); name[19] = 0; } double Circle::Get_Radius() { return radius; } char* Circle::Get_Name() { return name; } double Circle::Get_Area() { return * radius * radius; } File Circle.cpp

20 20 Creating Objects The class definition does not do anything! Doesn't allocate memory. Doesn't store data. Doesn't perform actions. It just defines a type. To do anything, we have to create an instance of the class. Call its methods to perform actions.

21 21 Objects An instance of a class is called an object. You can create any number of instances of a given class. Each has its own Identity Lifetime Data When you call a class method, you call it through a particular object. The method sees the data associated with that object.

22 22 Interface vs. Implementation The public definitions comprise the interface for the class A contract between the creator of the class and the users of the class. Should never change. Corresponds to the abstract data type. Implementation is private Users cannot see. Users cannot have dependencies. Can be changed without affecting users.

23 Class vs. ADT Our C++ class is usually just an approximation to the abstract data type. Floating point arithmetic is inexact. Operations can fail due to overflow and underflow. 23

24 24 Using Classes and Objects Classes and objects are used like traditional types and variables: Declare variables Circle c1("Circle_1", 5); Objects can be member variables in other classes. Assignment c2 = c1; Function arguments picture1.crop (c1);

25 25 Using Classes and Objects In C++ we can create objects by simply declaring them. Same as ints, doubles, etc.

26 26 Example: Using Class Circle #include #include "Circle.h" using namespace std; int main() { Circle c1("Circle_1", 5); double c1_area = c1.Get_Area(); cout << "Area of circle " << c1.Get_Name() << " is " << c1_area << endl; cin.get(); } File Circle_Demo.cpp

27 27 Program Circle_Demo Running

28 28 A Violation of Encapsulation As currently defined, class Circle gives its clients direct access to some of its data. What is the flaw?

29 29 A Violation of Encapsulation Method Get_Name() returns a pointer to the private member, name. Client can use the pointer to modify the object's name. BAD!

30 30 Exploiting a Flaw Add to main(): char* name = c1.Get_Name(); strcpy(name, "New Name"); cout << "Area of circle " << name << " is " << c1_area << endl;

31 31 Program Running

32 32 Patching the Hole To prevent clients from changing the name of a Circle object, modify the Get_Name() method to return a const pointer. In Circle.h: const char* Circle::Get_Name() In Circle.cpp: const char* Circle::Get_Name() { return name; }

33 33 Patching the Hole Now char* name = c1.Get_Name(); gets a compile error. Change it to const char* name = c1.Get_Name();

34 34 Patching the Hole Now strcpy(name, "New Name"); gets a compile error. The first argument to strcpy can't be a const pointer. The circle’s name is now safe from tampering.

35 35 A Minor Improvement All of the accessor functions (Get_xxx) are intended to just return information to the caller. Should never modify the object. We can express that intent by declaring the methods as const.

36 36 Circle.h // Return the radius of this circle. double Get_Radius() const; // Return the area of this circle. double Get_Area() const; // Return the name of this circle. const char* Get_Name() const; Same changes in Circle.cpp

37 37 About const methods “const” doesn't change the functionality of these methods. Makes our intentions clear to a reader. Causes compile error if someone later changes the method so that it modifies the object. It is good practice to define a method as const if that is our intent.

38 38 Dynamic Allocation Storage for objects declared as local variables is allocated on the run time stack. Like other local variables. We can dynamically allocate objects using the keyword "new". Space will be allocated on the heap. Like malloc in C. Object exists beyond the lifetime of the function that creates it. Invokes constructor to initialize the object. We get a pointer to the object.

39 39 Dynamic Allocation #include #include "Circle.h" using namespace std; int main() { Circle* c1; c1 = new Circle("Circle_1", 5.0); double c1_area = c1->Get_Area(); const char* name = c1->Get_Name(); cout << "Area of circle " << name << " is " << c1_area << endl; cin.get(); }

40 40 Program Running

41 41 Deallocation Objects allocated by declaration are deallocated when the function exits. Like all local variables. Objects allocated with “new” continue to exist until explicitly deleted. delete c1; Must hold on to pointer until the object is deleted. Else memory leak!

42 42 Explicitly Deleting an Object int main() { Circle* c1 = new Circle("Circle_1", 5); double c1_area = c1->Get_Area(); const char* name = c1->Get_Name(); cout << "Area of circle " << name << " is " << c1_area << endl; delete c1; c1 = 0; cin.get(); }

43 43 Works the same.

44 44 A Dangling Pointer After Circle c1 has been deleted, the variable name (in main) is a dangling pointer. Pointer to something that no longer exists. If we try to use it, the results are unpredictable.

45 45 Add to main() int main() { Circle* c1; c1 = new Circle("Circle_1", 5.0); double c1_area = c1->Get_Area(); const char* name = c1->Get_Name(); cout << "Area of circle " << name << " is " << c1_area << endl; delete c1; c1 = 0; cout << "Area of circle " << name << " is " << c1_area << endl; cin.get(); }

46 46 Program Runnning

47 47 Conclusion Since we never know when a dynamically allocated object may be deleted, don’t let a method return a pointer to its data. Require the client to provide the memory and copy the data into it. Copy semantics

48 48 New Get_Name Method In Circle.h: void Get_Name(char* buffer) const; In Circle.cpp: void Circle::Get_Name(char* buffer) const { strcpy(buffer, name); }

49 49 In Circle_Demo.cpp c1 = new Circle("Circle_1", 5); c1_area = c1->Get_Area(); //const char* name = c1->Get_Name(); char name[20]; c1->Get_Name(name); cout << "Area of circle " << name << " is " << c1_area << endl; delete c1; c1 = 0; cout << "Area of circle " << name << " is " << c1_area << endl;

50 50 Program Running The program now works as intended.

51 51 Hidden Coupling How did we know the maximum length for a name in main? char name[20]; c1->Get_Name(name); Is this a problem?

52 52 A Better Solution class Circle { public: static const int Max_Name_Len = 19; private: double radius; char name[Max_Name_Len+1]; public: // Constructor Circle(const char* n, double r); // Return the radius of this circle. double Get_Radius() const; // Return the name of this circle. const char* Get_Name() const; // Return the area of this circle. double Get_Area() const; };

53 53 Circle.cpp Circle::Circle(const char* name_, double radius_) { assert(radius >= 0.0); radius = r; strncpy(name, name_, Max_Name_Len); name[Max_Name_Len] = 0; }

54 54 In Circle_Demo.cpp //const char* name = c1->Get_Name(); char name[Circle::Max_Name_Len+1]; c1->Get_Name(name); cout << "Area of circle " << name << " is " << c1_area << endl;

55 55 Works the Same

56 56 Getting User Input What if we want the user to specify the name and radius of a Circle. Could overload the constructor and provide a version that asks for input. Better to provide a separate function outside the class definition. Separate user interface from class logic. Let’s write a function that asks the user for the name and radius and creates a Circle of that radius.

57 57 Getting User Input Circle* Create_Circle () { char name[Circle::Max_Name_Len+1]; double radius; cout << "Circle names can be up to " << Circle::Max_Name_Len << " characters\n"; cout << "Please enter name for a new circle: "; cin.getline(name, Circle::Max_Name_Len+1); cout << "Please enter radius: "; cin >> radius; cin.get(); // Clear newline char return new Circle (name, radius); } In file Circle_Demo.cpp (above main() )

58 58 Getting User Input int main() { Circle* c1; double c1_area; char name[Circle::Max_Name_Len+1]; c1 = Create_Circle(); c1_area = c1->Get_Area(); c1->Get_Name(name); cout << "Area of circle " << name << " is " << c1_area << endl; cin.get(); } In file Circle_Demo.cpp

59 59 Program Circle Running

60 60 Summary An abstract data type is defined in terms of its values and its operations. The implementation of an abstract data type should ensure that clients cannot change its data except by invoking its methods. Don’t give clients a pointer to anything inside an object. Clients should not need to know anything that is not in a public section of the class declaration. Don’t include user interface operations with the implementation of an abstract data type.

61 61 Assignment Do the examples from today’s class for yourself. Read (skim) Chapter 1 of Drozdek..


Download ppt "1 Abstract Data Types Chapter 1. 2 Objectives You will be able to: 1. Say what an abstract data type is. 2. Implement a simple abstract data type in C++"

Similar presentations


Ads by Google