Advanced Topics
COSC1076 Week 11
Skill Progression in this Course
Copyright By PowCoder代写 加微信 powcoder
Software Design
Implementation
Week 11 | Advanced Topics COSC1076
Abstract Classes Operator Overloading Lambda Functions Code Re-use Extraneous Copying
Week 11 | Advanced Topics COSC1076
Abstract Classes
Abstract Classes
An Abstract Class defines methods that must be implemented by derived classes
• It may also defined public and protected fields that derived classes may use • It should specify any contracts (pre- and post-conditions) for the methods
You cannot create an object of an Abstract Class. • You may only create objects of derived classes
The class still defines a valid polymorphic valid type.
• Thus you can have pointers and references to an abstract class type. • You can cast between abstract class types
Abstract Classes are similar to interfaces in Java
Week 11 | Advanced Topics COSC1076
Abstract Classes
An Abstract Classes is created by making one or more methods of the class “abstract” (by ‘setting it to zero’).
• All abstract methods must be virtual
class LinkedList {
virtual int size() = 0;
virtual void clear() = 0;
virtual int get(int i) = 0;
Week 11 | Advanced Topics COSC1076
Benefit of Abstract Classes
Abstract Classes allow “generic” or common behaviour of an ADT to be defined
• Without having to provide a direct implementation
• Allows implementations of the ADT to be swapped without changing any of the types within code that uses the ADT defined on an abstract class
Abstract classes can provide code implementations
• Allows for code-reuse through the common base class
Should only be used where the benefit to have polymorphic types or multiple varying implementations is required
Example use:
• Abstract I/O in C++
-std::istream
-std::ostream
Week 11 | Advanced Topics COSC1076
Operator Overloading
Operator Overloading
Permits classes to make use of the 38 C++ operators, including: • Comparison operators: ==, !=, <, <=, >, >=
• Arithmetic operators: +, -, *, /, %, ^, +=, -=, etc.
• Increment/Decrement: ++, —
• Assignment operator: = • I/O operators: <<, >>
• Access: [], *, ->, &
Generally operators can be divided into:
• Operators that do not modify the class
• Operators that modify the class, and return it • Operators that return a new class
https://en.cppreference.com/w/cpp/language/operators
Week 11 | Advanced Topics COSC1076
Operator Overloading
Operators can be overloaded through:
• Methods (member functions) on a class • Functions external to the class
For this course we will stick to member functions, though the concept for function versions is very similar
Week 11 | Advanced Topics COSC1076
Operator Overloading
In an expression:
lhs
The overloaded operator method is called on the object on the left-hand side • The object on the right-hand side is passed as a parameter
Week 11 | Advanced Topics COSC1076
Comparison Operators
All comparison operators take the form:
bool operator???(const Class& rhs) const;
• They return a bool
• Take the RHS as a constant reference • Are a const method
You have to implement any comparison operator you wish to use: • But, only really need to implement two:
• The other comparison operators are implemented from these
bool operator==(const Class& rhs) const;
bool operator<(const Class& rhs) const;
Week 11 | Advanced Topics COSC1076
Access Operator
The square bracket access operator[]
type& operator[](const int index);
• Note how it returns a reference!
• This is a reference to the index being accessed • Allows the value at the index to be updated
Week 11 | Advanced Topics COSC1076
Arithmetic Operators (self modifying)
Some arithmetic operators directly modify the object itself:
• Still return a reference to the current object
- This is for operator chaining reasons
- ALL c++ operators return a value - none are void
• The parameter can be of any desirable type to add to the object
Object& operator+=(const Object& other);
Object& operator+=(int value);
Week 11 | Advanced Topics COSC1076
Arithmetic Operators (new)
Some arithmetic operators generate a new object:
Object operator+(const Object& other) const; • Generate a new object
- The new object is the result of the arithmetic operation • Does NOT modify the object itself
- This is why it is const
Week 11 | Advanced Topics COSC1076
Assignment Operator
Replaces the contents of the current object with a COPY of the contents of the object passed as the parameter:
Object& operator=(const Object& other);
• Differs from a copy constructor as this modifies an existing object • Returns a reference to the current object (after modification)
Week 11 | Advanced Topics COSC1076
Increment Operators
Pre-increment
Object& operator++(); • Modifies the existing object
• Returns a reference to the existing object
Post-increment
Object operator++(int); • COPIES the object first
• Then increments
• Then returns the copy (not it is not a reference)
• Requires a different parameter (which is ignored) to permit the overloading
Week 11 | Advanced Topics COSC1076
Stream Operators
A stream operator MUST be defined as non-member functions. That is, they cannot be methods of the class, but defined outside of the class.
std::ostream& operator<<(std::ostream& os, other& vec); • Outputs the operator to the provided output stream
• Returns a reference to the stream that was written to
Week 11 | Advanced Topics COSC1076
Lambda Functions
Lambda Functions
Lambda Functions are function that sit within the scope of another function
They allow for:
• Local code re-use to avoid duplication of the same logic
• Prevent are large scope or namespace (such as a class or C++ file) to be “polluted” by additional functions/methods which should really be contained to a small local scope
Issues include:
• Should be kept small and simple, otherwise they causes code-readability issues
• May result in code duplication (of the same lambda function) across a large scope/file since non of those methods export the duplicated logic
Week 11 | Advanced Topics COSC1076
Lambda Functions
Lambda Functions work identically to normal function/methods, with one exception
• The function can capture variables from the scope of the external function • Variables can be captured:
- By explicit name (as a copy or reference)
- By default (capture all external variables that are used)
- [=] by copy
- [&] by reference
auto name = [capture]( params ) {
Week 11 | Advanced Topics COSC1076
Code Re-use
Class: Code Re-use
Where possible, a derived class should re-use as much code as possible from it’s base class(es), rather than overriding and re-implementing methods
Things to consider include:
• If a method requires no changes, it should not be overridden
• An overriden method should call the base class version for common code
• If multiple derived classes use similar logic, that should be placed as a protected method in the base class
Week 11 | Advanced Topics COSC1076
Polymorphism: Code Re-use
The most appropriate class should be used in the code
Things to consider include:
• A good principle is to use the most “general” base class for any block of code
- This is determined by what methods need to be called
- What other code may be passed the object • Typecasting should be avoided
Week 11 | Advanced Topics COSC1076
Generics: Code Re-use
Place logic that is identical, except for the types involved, into a single place Allow the compiler to generate the necessary code for each type
Week 11 | Advanced Topics COSC1076
Operator Overloading: Code Re-use
Allow re-use of standard operators and concepts when writing code • Such as assignment, comparison, I/O, etc.
Reduces the need to manually specify custom functions/methods • See Java .equals(), etc.
Can make code more easy to “intuitively” interpret • Such as operator+() on std::string
Week 11 | Advanced Topics COSC1076
Function: Code Re-use
Have seen in many courses the purpose of modularity
Splitting code into functions allows those functions to be re-used, rather than re-written
Week 11 | Advanced Topics COSC1076
Lambda Function: Code Re-use
Allow the principle of function re-use, but keep that re-use to a localised scope
Week 11 | Advanced Topics COSC1076
Warning: DANGER!
As with all discussions in this course there is a but...
• Having too many external code-dependencies (ie library code-reuse) • Ensuring external dependencies are actually correct and necessary
Week 11 | Advanced Topics COSC1076
Warning: Leftpad
Week 11 | Advanced Topics COSC1076
An iterator is a generalised pointer into a container
• The pointer “deferences” to a specific element of the container
• The iterator may be “stepped” to access the “next” element of the container • The order of iteration depends on the container
C++14 supports various types of iterators with various restrictions • For this discussion, we stick to random-access iterators
C++ STL containers have methods to work with iterators
• begin() - an iterator pointer to the “first” element of the container
• end() - an iterator pointer to the element “beyond” the “last” element of the container
Week 11 | Advanced Topics COSC1076
Typical Use:
for(std::vector
it != vec.end();
cout << "vec[?] = " << *it << endl;
Iterators are “stepped” using:
• Increment/decrement operators - preferred
• Addition/Subtraction operators - possible in certain circumstances
The value “pointed to” by an iterator is accessed by • Dereferencing the iterator
Week 11 | Advanced Topics COSC1076
Typical Use:
for(std::vector
it != vec.end();
cout << "vec[?] = " << *it << endl;
The iterator type is typically defined within a class: • In general, use
Iterators can be compared (==/!=)
• Two iterators are the same if they point to the same element of the container
Week 11 | Advanced Topics COSC1076
• Provide a generic, type independent approach to iterating through the elements of a container
• Algorithms can be written that operate over iterators – Rather than the container directly
• Iterators are frequently used within the C++ STL – Not explored in depth in this course
• Typically more efficient at accessing elements of a container than directly random-access methods (if iteration is desired)
Week 11 | Advanced Topics COSC1076
What does the assignment operator (=) do?
What actually happens in a statement?
Case 1: Assignment with Classes
Assignment operator does an explicit duplication/copy If no assignment operator?
Vector v1;
Vector v2;
Week 11 | Advanced Topics COSC1076
Case 2: Passing by Value
Pass-by-value must duplicate the object, • Calls the copy constructor
Vector v1;
printVector(v1);
void printVector(Vector v) {
for (int i = 0; i != 10; ++i) {
cout << "v1[" << i << "]: " << v[i] << endl;
Week 11 | Advanced Topics COSC1076
Case 3: Returning an Object
In C++14, according to the language specification, gives a copy
• Return Value Optimisation converts this is a direct initialisation • Remove the copy
Vector v1 = newVector();
Vector newVector() {
v[0] = 42;
Week 11 | Advanced Topics COSC1076
Case 4: Increment, pre vs post
There is a significant difference between pre and post increment operators • The optimiser may not be able to “optimise-out” the unnecessary copy
Vector v1;
for (int i = 0; i != 5; i++) {
cout << "i = " << i << endl;
printVector(v1);
Week 11 | Advanced Topics COSC1076
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com