Week 7 - Gemini Flashcards
(30 cards)
What is ‘operator overloading’ in C++?
Operator overloading allows you to redefine the behavior of existing C++ operators (like +
, -
, *
, /
, <<
, ==
, []
) for user-defined types (classes). This means you can make operators work intuitively with objects of your classes.
What is the general syntax for declaring an overloaded operator function?
ReturnType operator@(parameters);
where @
is the operator symbol being overloaded (e.g., operator+
, operator<<
).
When overloading a binary operator (e.g., +
for Complex a + b;
), how many arguments does the member function version take, and how many does the non-member (friend) function version take?
Member function version: Takes one argument (the right-hand operand, e.g., Complex Complex::operator+(const Complex& other)
). The left-hand operand is the this
object. Non-member/friend function version: Takes two arguments (both operands, e.g., Complex operator+(const Complex& lhs, const Complex& rhs)
).
Why must the stream insertion (<<
) and extraction (>>
) operators typically be overloaded as non-member (often friend) functions?
Because the left-hand operand is an ostream object (e.g., cout
) or istream object (e.g., cin
), which are not part of your class. A member function would require the class object to be on the left (e.g., myObject << cout;
which is unnatural).
What is the typical signature for an overloaded stream insertion operator <<
for a class MyClass
?
std::ostream& operator<<(std::ostream& os, const MyClass& obj);
It takes an ostream
reference and a const
reference to the class object, and returns an ostream
reference to allow chaining.
Which operators in C++ cannot be overloaded?
Scope resolution (::
), conditional (?:
), sizeof
, member selector (.
), member pointer selector (.*
), and preprocessor symbols (#
, ##
).
Can you change the precedence, associativity, or number of operands of an operator when overloading it?
No. The original precedence, associativity, and arity (number of operands) of the operator are preserved.
What is a const
member function in a C++ class (e.g., double getValue() const;
)? What does it guarantee?
A const
member function guarantees that it will not modify any non-static data members of the object on which it is called. It can be invoked on both const
and non-const
objects of the class.
What happens if a const
member function attempts to modify a member variable or call a non-const
member function?
The compiler will generate an error, as this violates the const
guarantee of the function.
When should a member function be declared as const
?
Any member function that does not alter the state of the object (i.e., does not change its member variables) should be declared const
. This is good practice for API design and allows the function to be used with const
objects.
What is an ‘inline function’ in C++? How can a member function be made inline?
An inline function is a request to the compiler to replace the function call with the actual function code at the call site, potentially reducing call overhead for small functions. Member functions defined within the class declaration are implicitly inline. Functions defined outside can be made inline by using the inline
keyword.
What is a friend
function of a class? What special privilege does it have?
A friend
function is a non-member function that is granted special permission to access the private
and protected
members of the class in which it is declared as a friend. Declaration: friend ReturnType functionName(parameters);
inside the class.
Give a common use case for declaring a non-member function as a friend
of a class.
Overloading binary operators (like +
, -
, *
, /
, <<
, >>
) where you want a symmetric feel or when the class object is not the left-hand operand (e.g., std::cout << myObject
).
When working with classes in multiple files, what typically goes into the header (.h
or .hpp
) file?
The class declaration (including member variable declarations and member function prototypes or declarations), typedefs
, constants related to the class, and include guards (#pragma once
or #ifndef/#define/#endif
).
When working with classes in multiple files, what typically goes into the source (.cpp
) file?
The definitions (implementations) of the class’s member functions (those not defined inline in the header), and definitions of static member variables. The source file must #include
its corresponding header file.
What is the purpose of #pragma once
or include guards (#ifndef HEADER_NAME_H ... #define HEADER_NAME_H ... #endif
) in a header file?
To prevent the contents of the header file from being included multiple times within a single translation unit, which would lead to redefinition errors during compilation.
Is it good practice to put using namespace std;
in a header file? Why or why not?
No, it’s generally bad practice. Header files can be included in many other files, and putting a using namespace
directive in a header pollutes the global namespace for every file that includes it, potentially leading to name collisions.
If a class manages a dynamically allocated resource (e.g., an array using new[]
in its constructor), what is the crucial role of the destructor?
The destructor must deallocate the dynamically allocated resource using delete[]
(or delete
for single objects) to prevent memory leaks when objects of the class are destroyed.
What is the ‘Rule of Three’ (or Five/Zero) in C++ when a class manages resources like dynamic memory? What three functions are typically needed?
When a class manages a resource that requires explicit deallocation (like dynamic memory), you usually need to define/delete/default: 1. A destructor (to free the resource). 2. A copy constructor (to handle correct copying of the resource, often a ‘deep copy’). 3. A copy assignment operator (operator=
) (to handle correct assignment, also often a ‘deep copy’). If these are not correctly handled, issues like shallow copies, double frees, or memory leaks can occur.
Explain ‘deep copy’ versus ‘shallow copy’ in the context of a class with a pointer member that manages dynamic memory.
Shallow copy: Only the pointer member is copied, so both the original and copied object point to the same dynamically allocated memory. This is problematic as deleting one object’s memory affects the other, leading to double frees or dangling pointers. Deep copy: New memory is allocated for the copied object, and the contents of the original dynamic memory are copied to this new memory. Each object manages its own distinct resource.
What is the purpose of overloading the subscript operator operator[]
for a custom class like YourVector
? (Sheet 4, Problem 2)
It allows objects of the class to be used with array-like syntax for element access. For example, myVector[i]
could return a reference to the i-th element, enabling both reading and writing.
How might you provide both const
and non-const
versions of the overloaded subscript operator []
for a class?
Provide two overloads: ValueType& operator[](int index);
(for non-const objects, allows modification) and const ValueType& operator[](int index) const;
(for const objects, allows read-only access).
What is std::vector
in C++ and which header is required to use it?
std::vector
is a dynamic array container from the C++ Standard Template Library (STL). It can grow or shrink in size automatically. Header: <vector>
.
How do you add an element to the end of a std::vector
named myVec
?
Using the push_back()
member function: myVec.push_back(value);
.