CISC 125 Exam 1 - Study Guide Questions and Answers

Answers generated with AI, please use other resources alongside to confirm accuracy.

Inheritance and Composition

Question Answer
1. What is the purpose of inheritance in Object Oriented Design? What type of relationship does it implement (has-a vs is-a)? Inheritance allows code reuse and the establishment of hierarchical relationships between classes. It implements an "is-a" relationship, meaning a derived class is-a specialized version of its base class (e.g., a Dog is-a Animal). This enables polymorphism and creates a hierarchy of related classes.
2. Describe how the access specifier protected differs from public and private in a class. Private: Only accessible within the class itself. Public: Accessible from anywhere (inside the class, outside the class, and in derived classes). Protected: Accessible within the class and by derived classes, but not from outside.
3. Give me an example of overloading a function (it can be from one of our coding examples) and an example of overriding a function. Overloading (compile-time polymorphism): Multiple functions with the same name but different parameter lists. Example: cout << 5 and cout << "hello" use the same operator<< overloaded for different types. Overriding (runtime polymorphism): A derived class provides a different implementation of a base class virtual function. Example: A Dog class overrides a virtual print() function from an Animal base class.
4. What is composition? In what order are the constructors called? Composition is a "has-a" relationship where a class contains objects of other classes as member variables. Constructor call order: (1) Base class constructor, (2) Member object constructors in the order they are declared, (3) Derived class constructor. Destructors are called in reverse order.
5. What is the default constructor? (How can you tell it's the default constructor?) When is it called? The default constructor is the constructor with no parameters. You can identify it by its empty parameter list (e.g., ClassName()). It is called automatically when an object is created without providing any arguments, or when an array of objects is created.

Chapter 12 - Pointers and Dynamic Memory

Question Answer
1. What is a pointer? Name one advantage to having pointers as part of C++. How do you declare a pointer? A pointer is a variable that stores the memory address of another variable. Advantages: (1) Dynamic memory allocation, (2) Efficient passing of large objects by reference, (3) Enables polymorphism through inheritance, (4) Allows building complex data structures. Declaration: int* ptr; or int *ptr; (the position of the * is flexible)
2. Explain what the * and & characters do when dealing with pointers. (* is used in two different ways.) The & operator is the address-of operator; it returns the memory address of a variable (e.g., &x gets the address of x). The * operator is used in two ways: (1) In declaration, it denotes a pointer type (int* ptr declares ptr as a pointer to int), (2) As a dereference operator, it accesses the value at the address the pointer points to (e.g., *ptr retrieves the value at that address).
3. Why should we always initialize a pointer to nullptr? Uninitialized pointers contain garbage values (random memory addresses), leading to undefined behavior if dereferenced. Initializing to nullptr prevents random memory access. It also allows safe checking (if (ptr != nullptr)) to verify whether a pointer is valid before use, preventing crashes from dereferencing invalid addresses.
4. See the picture in slide 8 & 9 in the generic pointer slides. Be able to explain what is happening in memory like in those slides. The slides show pointer memory diagrams: (1) A pointer variable holds a memory address, shown as boxes at different memory locations. (2) The & operator gets the address of a variable (e.g., p = &num makes p store the address 1800 where num is located). (3) The * operator dereferences a pointer to access the value at that address (e.g., *p = 24 stores 24 at the location p points to, changing num's value). (4) Each variable occupies a memory location with an address, and pointers allow indirect access to those locations.
5. What is a dynamic array? What is special about dynamic memory? A dynamic array is allocated at runtime on the heap using new: int* arr = new int[10];. Special characteristics: (1) Size can be determined at runtime, (2) Lives on the heap (not limited by stack size), (3) Lifetime extends until explicitly deleted, (4) Must be manually deallocated with delete[], (5) Allows for more flexible memory management than static arrays.
6. What does this do: *(arr+i)? What can I use instead? *(arr+i) accesses the element at index i in an array using pointer arithmetic. It dereferences the pointer (arr+i), returning the value at that memory location. Alternative: arr[i] is equivalent and more readable. Both perform the same operation - accessing the i-th element of the array.
7. What is the benefit of passing a pointer to a function? Can you return a pointer from a function? Benefits of passing pointers: (1) Avoids copying large objects, improving efficiency, (2) Allows the function to modify the original variable (pass by reference), (3) Pointers can be null, allowing optional parameters. Yes, you can return a pointer, but be cautious: avoid returning pointers to local variables (dangling pointer). Return pointers to dynamically allocated memory or to objects that exist beyond the function's scope.
8. When do we use ->? The -> operator is used to access members of an object through a pointer. Syntax: pointer->member is equivalent to (*pointer).member. Example: if ptr points to an object of class Dog with a member age, you use ptr->age to access it.
9. When are destructors called (two different ways)? Destructors are called in two ways: (1) When an automatically allocated object (on the stack) goes out of scope, the destructor is called automatically. (2) When a dynamically allocated object (on the heap) is explicitly deleted using the delete operator, the destructor is called.
10. What is the difference between shallow and deep copies of arrays? How do you implement them? Shallow copy: Only copies the pointer value; both objects point to the same memory. Causes issues if one object deletes the memory. Deep copy: Allocates new memory and copies the actual data. Implementation: Define a copy constructor and an assignment operator (operator=) that allocate new memory and copy the data member-by-member. The destructor should also be defined to properly deallocate memory.
11. If a class has a pointer data member, what two functions must be defined for it and why? The two functions that must be defined are: (1) Copy constructor: to create a proper deep copy when an object is copied, and (2) Assignment operator (operator=): to perform deep copy assignment. These are necessary because the default versions only do shallow copies, which leads to double-deletion and memory errors when objects are destroyed.
12. What are the 3 instances when a copy constructor gets called? The copy constructor is called in three instances: (1) When passing an object by value to a function, (2) When returning an object by value from a function, (3) When initializing a new object with an existing object of the same class (e.g., MyClass obj2 = obj1;).
13. Class B inherits from Class A. Can you assign an object of Class A to Class B? Can you assign an object of class B to class A? Assign Class A to Class B: No, because B is a derived class (more specific) than A. A pointer or reference to B cannot be initialized with an A object. Assign Class B to Class A: Yes (through a base class pointer or reference), because B is-a A. A base class can reference a derived class object, though information specific to B is lost if stored in an A object.
14. What is the difference between dynamic(run time) and static(compile time) binding? How does defining a function as virtual contribute to the binding? Static binding (compile-time): The function to be called is determined at compile time based on the declared type. Dynamic binding (runtime): The function to be called is determined at runtime based on the actual object type. Defining a function as virtual enables dynamic binding. Without virtual, derived class functions are statically bound and won't be called through a base class pointer; with virtual, the actual object's version is called.
15. Be able to explain what is happening in slide 8 of Chapter 12 part 3 - which print is getting called and why? What would happen if pet and dog were objects instead of pointers? When pet and dog are objects (not pointers): pet = dog; causes type slicing. The dogType object is converted to a petType object, and any derived class data members (like breed) are lost. You can only access base class members through pet. If you try to call a function only available in the derived class (like pet.setBreed()), you get a compile-time error. With pointers, pet would point to the actual dogType object, and virtual functions would dynamically bind to the correct derived class version at runtime.
16. How does dynamic binding contribute to polymorphism? Dynamic binding enables polymorphism by allowing the same function call to behave differently depending on the actual object type at runtime. Through base class pointers/references, you can call virtual functions on derived class objects, and the correct derived class version is executed. This allows writing generic code that works with multiple derived classes without knowing their specific types at compile time.
17. How should having a virtual function affect the destructor? Why? If a class has virtual functions, its destructor should also be virtual. This ensures that when a derived class object is deleted through a base class pointer, the derived class destructor is called first (via dynamic binding), properly cleaning up derived class resources before the base class destructor is called. Without a virtual destructor, only the base class destructor runs, leaving derived class resources uncleared.
18. What is a pure virtual function? How do we make a function "pure virtual"? What is the effect on a class with a pure virtual function? A pure virtual function is a virtual function with no implementation in the base class, serving as an interface that derived classes must implement. Syntax: virtual void functionName() = 0; The =0 denotes a pure virtual function. Effect: A class containing one or more pure virtual functions becomes an abstract class and cannot be instantiated. Derived classes must provide implementations for all pure virtual functions to be concrete classes.