Chapter 4 Classes
unset4-1 Explain the role of public and private. What are the differences between public and private members?unsetunset
Answer: Public members are declared with the <span>public</span> keyword, defining the external interface of the class, allowing external objects to access them directly; private members are declared with the <span>private</span> keyword, allowing access only by member functions of the class, and any direct access from outside the class is illegal. Private members are hidden within the class, preventing direct manipulation from outside, effectively controlling access permissions and ensuring data security.
unsetunset4-2 What is the role of the protected keyword?unsetunset
Answer: The <span>protected</span> keyword is used to declare protected members, whose access permissions are between <span>public</span> and <span>private</span>:
- Member functions of the class can access them directly;
- Member functions of derived classes (subclasses) can access them directly;
- Non-derived class objects outside the class cannot access them directly. Its core function is to support the inheritance mechanism of classes: it prevents base class members from being modified arbitrarily by external entities while allowing derived classes to inherit and reasonably use these members, achieving flexible control over access permissions.
unsetunset4-3 What are the roles of constructors and destructors?unsetunset
Answer: The role of a constructor is to initialize an object with specific values when it is created, setting the object to a specific state (endowing the object with unique characteristics), completing the instantiation process from “general to specific”. The constructor is automatically called by the system when the object is created, requiring no manual triggering. The destructor serves the opposite purpose of the constructor, performing cleanup tasks before the object is destroyed (such as releasing dynamically allocated memory, closing files, etc.). The destructor is automatically called by the system when the object’s lifetime ends, and after the call, the memory occupied by the object will be released.
unsetunset4-4 Can data members be public? Can member functions be private?unsetunset
Answer: Yes, both are legal. Data members and member functions can be declared as <span>public</span> or <span>private</span>:
- Public data members allow external access directly, but this breaks data encapsulation and increases the risk of illegal modifications, so it is not recommended to set data members as
<span>public</span>; - Private member functions can only be called by other member functions of the class, often used to encapsulate internal logic (which does not need to be perceived externally), in line with the encapsulation idea of “hiding implementation details”. In actual development, data members are usually set as
<span>private</span>, accessed indirectly through public member functions (interfaces) to ensure data security.
unsetunset4-5 Given that class A has a data member int a, can the values of the data members a of two objects A1 and A2 of A be different?unsetunset
Answer: Yes. A class is a “template” for objects, and each object will independently allocate memory to store its own data members, so the data members of different objects do not interfere with each other, allowing A1 and A2’s <span>a</span> values to be different.
unsetunset4-6 What is a copy constructor? When is a copy constructor called?unsetunset
Answer: A copy constructor is a special type of constructor that meets the following characteristics:
- The function name is the same as the class name;
- The parameter is a reference to an object of the same class (usually marked with
<span>const</span>to avoid modifying the source object); - It has no return value (consistent with ordinary constructors). Its role is to initialize a new object of the same class using an existing object.
The copy constructor is called in the following three situations:
- When initializing a new object with an existing object (e.g.,
<span>A obj2(obj1);</span>); - When the function parameter is a class object (value passing), binding the actual parameter and formal parameter (passing parameters);
- When the function return value is a class object, the return result is created through the copy constructor (a temporary object is created for the return value).
unsetunset4-7 What are the differences between copy constructors and assignment operators (=)?unsetunset
Answer: The core differences between copy constructors and assignment operators lie in the timing of their actions, scenarios, and memory behavior, as follows:
| Comparison Dimension | Copy Constructor | Assignment Operator (=) |
|---|---|---|
| Timing of Action | When creating a new object (initialization process) | Between existing objects (assignment after objects are created) |
| Calling Scenario | Initializing a new object with an object, value passing, returning class objects | Assignment operation between two existing objects (e.g., <span>obj2 = obj1</span>) |
| Memory Behavior | Allocates independent memory for the new object, initializing data | Does not allocate new memory, only overwrites existing object data |
| Default Behavior | Compiler generates a default shallow copy version | Compiler generates a default shallow copy version |
| Deep Copy Requirement | Needs to be manually overloaded when the class contains dynamic memory | Needs to be manually overloaded when the class contains dynamic memory (to avoid shallow copy issues) |
Example:
A obj1;
A obj2(obj1); // Calls the copy constructor (obj2 is a new object)
A obj3;
obj3 = obj1; // Calls the assignment operator (obj3 already exists)
unsetunset4-8 Define a Dog class with properties such as age and weight, and methods to operate on these properties. Implement and test this class.unsetunset
Answer: Source code:
#include <iostream>
using namespace std;
class Dog {
public:
// Constructor with default parameters
Dog(int initialAge = 0, int initialWeight = 5);
~Dog();
// Inline member functions (get properties)
int GetAge() { return itsAge; }
void SetAge(int age) { itsAge = age; }
int GetWeight() { return itsWeight; }
void SetWeight(int weight) { itsWeight = weight; } // Corrected original logic error (originally assigned to itsAge)
private:
int itsAge, itsWeight;
};
// Constructor implementation
Dog::Dog(int initialAge, int initialWeight) {
itsAge = initialAge;
itsWeight = initialWeight;
}
// Destructor (no specific cleanup work)
Dog::~Dog() {}
int main() {
Dog Jack(2, 10);
cout << "Jack is a Dog who is " << Jack.GetAge()
<< " years old and " << Jack.GetWeight() << " pounds weight.\n";
Jack.SetAge(7);
Jack.SetWeight(20);
cout << "Now Jack is " << Jack.GetAge()
<< " years old and " << Jack.GetWeight() << " pounds weight.\n";
return 0;
}
Program output:
Jack is a Dog who is 2 years old and 10 pounds weight.
Now Jack is 7 years old and 20 pounds weight.
unsetunset4-9 Design and test a Rectangle class with properties for the coordinates of the lower left and upper right corners, capable of calculating the area of the rectangle.unsetunset
Answer: Source code:
#include <iostream>
using namespace std;
class Rectangle {
public:
// Constructor: parameter order (top, left, bottom, right)
Rectangle(int top, int left, int bottom, int right);
~Rectangle() {} // Destructor (no cleanup work)
// Inline member functions (get coordinate properties)
int GetTop() const { return itsTop; }
int GetLeft() const { return itsLeft; }
int GetBottom() const { return itsBottom; }
int GetRight() const { return itsRight; }
// Inline member functions (set coordinate properties)
void SetTop(int top) { itsTop = top; }
void SetLeft(int left) { itsLeft = left; }
void SetBottom(int bottom) { itsBottom = bottom; }
void SetRight(int right) { itsRight = right; }
// Member function to calculate area
int GetArea() const;
private:
int itsTop; // Upper right y-coordinate
int itsLeft; // Lower left x-coordinate
int itsBottom; // Lower left y-coordinate
int itsRight; // Upper right x-coordinate
};
// Constructor implementation (corrected original missing itsLeft assignment)
Rectangle::Rectangle(int top, int left, int bottom, int right) {
itsTop = top;
itsLeft = left;
itsBottom = bottom;
itsRight = right;
}
// Area calculation: width = right - left, height = top - bottom (assuming top>bottom, right>left)
int Rectangle::GetArea() const {
int Width = itsRight - itsLeft;
int Height = itsTop - itsBottom;
return Width * Height;
}
int main() {
// Rectangle: top=100, left=20, bottom=50, right=80
Rectangle MyRectangle(100, 20, 50, 80);
int Area = MyRectangle.GetArea();
cout << "Area: " << Area << "\n";
return 0;
}
Program output:
Area: 3000
unsetunset4-10 Design a People class for personnel management. Considering generality, only abstract the properties that all types of personnel have: number, sex, birthday, ID number, etc. The “birthday” is defined as an embedded “date” class object. Implement member functions for entering and displaying personnel information. Requirements include: constructor and destructor, copy constructor, inline member functions, member functions with default parameter values, and aggregation.unsetunset
Answer: This question is used as an optional question for Experiment 4, so no answer is provided.
unsetunset4-11 Define a Rectangle class with length and width properties, and a member function to calculate the area of the rectangle.unsetunset
Answer: Source code:
#include <iostream>
using namespace std;
class Rectangle {
public:
// Constructor (initialize length and width)
Rectangle(float len, float width) {
Length = len;
Width = width;
}
~Rectangle() {} // Destructor (no cleanup work)
// Inline member functions (calculate area, get properties)
float GetArea() { return Length * Width; }
float GetLength() { return Length; }
float GetWidth() { return Width; }
private:
float Length; // Length
float Width; // Width
};
int main() {
float length, width;
cout << "Please enter the length of the rectangle:";
cin >> length;
cout << "Please enter the width of the rectangle:";
cin >> width;
Rectangle r(length, width);
cout << "The area of the rectangle with length " << length << " and width " << width
<< " is: " << r.GetArea() << endl;
return 0;
}
Program output:
Please enter the length of the rectangle:5
Please enter the width of the rectangle:4
The area of the rectangle with length 5 and width 4 is: 20
unsetunset4-12 Define a “datatype” class that can handle data of character, integer, and floating-point types, and provide its constructor.unsetunset
Answer: Source code:
#include <iostream>
using namespace std;
class datatype {
// Enumeration: identifies the current stored data type
enum {
character, // Character type
integer, // Integer type (corrected original missing enumeration value)
floating_point // Floating-point type
} vartype;
// Union: stores different types of data (saves memory)
union {
char c; // Character data
int i; // Integer data
float f; // Floating-point data
};
public:
// Constructor (receives character, integer, and floating-point parameters)
datatype(char ch) {
vartype = character;
c = ch;
}
datatype(int ii) {
vartype = integer;
i = ii;
}
datatype(float ff) {
vartype = floating_point;
f = ff;
}
// Print data (output based on type)
void print();
};
void datatype::print() {
switch (vartype) {
case character:
cout << "Character type: " << c << endl;
break;
case integer:
cout << "Integer type: " << i << endl;
break;
case floating_point:
cout << "Floating-point type: " << f << endl;
break;
}
}
int main() {
datatype A('c'), B(12), C(1.44F);
A.print();
B.print();
C.print();
return 0;
}
Program output:
Character type: c
Integer type: 12
Floating-point type: 1.44
unsetunset4-13 Define a Circle class with a data member radius, and a member function GetArea() to calculate the area of the circle. Create a Circle object for testing.unsetunset
Answer: Source code:
#include <iostream>
using namespace std;
class Circle {
public:
// Constructor (initialize radius)
Circle(float radius) { Radius = radius; }
~Circle() {} // Destructor (no cleanup work)
// Calculate the area of the circle (π is taken as 3.14)
float GetArea() { return 3.14 * Radius * Radius; }
private:
float Radius; // Radius
};
int main() {
float radius;
cout << "Please enter the radius of the circle:";
cin >> radius;
Circle p(radius);
cout << "The area of the circle with radius " << radius << " is: " << p.GetArea() << endl;
return 0;
}
Program output:
Please enter the radius of the circle:5
The area of the circle with radius 5 is: 78.5
unsetunset4-14 Define a Tree class with a member ages, and a member function grow(int years) to add years to ages, and age() to display the value of ages for the Tree object.unsetunset
Answer: Source code:
#include <iostream>
using namespace std;
class Tree {
int ages; // Age of the tree
public:
Tree(int n = 0); // Constructor with default parameter
~Tree(); // Destructor
void grow(int years); // Grow (increase age)
void age(); // Display age
};
// Constructor implementation
Tree::Tree(int n) {
ages = n;
}
// Destructor (displays final age)
Tree::~Tree() {
age();
}
// Grow function: age increases by years
void Tree::grow(int years) {
ages += years;
}
// Display age
void Tree::age() {
cout << "The age of this tree is " << ages << endl;
}
int main() {
Tree t(12); // Create tree object, initial age 12
t.age(); // Display initial age
t.grow(4); // Grow for 4 years (final age displayed in destructor)
return 0;
}
Program output:
The age of this tree is 12
The age of this tree is 16