const
, struct
s, and C-Style ADTs
const
, struct
s, and C-Style ADTsAs we start to work with larger, more complex programs, abstraction helps manage that complexity. We've already discussed procedural abstraction, i.e. using functions to break down the flow of our program into manageable sub-tasks.
Today, we'll introduce Abstract Data Types (ADTs), which serve as a combined abstraction for data and the functions that operate on that data.
Specifically, we'll define some conventions for ADTs as they could be implemented in the C language (which is both the precursor to C++ and also a contemporary language that used in lower-level systems development). We're starting here for a few reasons:
But first, let's take a detour to formally acknowledge the const
keyeword, which has been showing up and will start showing up even more in the near future…
1: The
1.1
const Keyword
The
1.1 The
const Keyword
Provided the declarations below, which of the following assignments cause a compiler error due to a violation of
You're welcome to check your solution with this walkthrough video: |
2:
2.1
const Conversions
The compiler also needs to decide where implicit conversions involving Perhaps the most important place these rules are realized is in function call parameters as a part of interface specification. Following the rules above, the compiler will only allow a function to be called on a
2.1
const in Function Parameters
Consider these function signatures and some variables declared in a One of the function calls in
For which function call does the compiler produce an error? Briefly explain why. Sample solution…The compiler will prohibit the call tored(x) since the parameter is pass-by-reference and does not maintain the const. If the call were allowed, the implementation of red could then potentially change the value of x , which was supposed to be const.
|
3: Intro to
3.1
struct s
Now, back to our main event… defining and using compound objects. To recap the fundamentals:
If you've got a Finally, we can work with structs via pointers. If you're doing that, the syntax for member access changes. For example, assume
Use the
3.1 Exercise: Practice with
structs
Complete each of the tasks described in the comments. Sample solution…
|
4:
4.1
struct s and Functions
We'll want to package up complex operations on Here's a written version of the flowchart in the video, for quick reference:
4.1 Exercise:
struct s and Functions
Each of the following implementations of
Sample solution…
|
5: C-Style ADTs
5.1
Structs form the foundation of ADTs in C, acting as a data representation that allows us to model heterogeneous real-world objects. What makes a full ADT is the introduction of associated behaviors (i.e. functions) as well as plain data. We implement these behaviors as associated functions, which operate on an ADT struct via a pointer parameter. Here's some details:
5.1 Exercise:
Triangle_scale()
Let's say we want to add a function to scale a triangle by a given factor. Here's an example:
Which of the implementations of
Sample solution…
|
6: ADT Initialization and Representation Invariants
An essential component of proper ADT design is the use of representation invariants to express conditions that differentiate valid data (e.g. a Triangle with sides 3, 4, and 5) from invalid, nonsense values (e.g. one of the side lengths is -10). There are two main perspectives on representation invariants when you're implementing code:
#1 is a bit of extra work we put in so that we can rely on #2. |
7: Interfaces and Implementations
Just a few high level comments on the relationship between interfaces and implementations in ADT design… |
8: ADTs in Project 2
8.1
Let's take a quick look at the way abstraction is used in project 2 to build
8.1
Which of the following are true about ADTs in project 2? |
9: Function Overloading
In C++ (and some other programming languages), it's allowed to have multiple functions with the same name as long as they have different parameter types. This is called function overloading. |
10: Unit Testing ADTs
Of course, just as we write unit tests for functions (which are the realization of procedural abstractions in our code), we should also write tests for ADTs to ensure that the behavior of their implementation matches with their specified interface. Let's take a look at this with some examples for testing the Fall 2024Please disregard the use of the |