简介
在本实验中,你将学习如何在 C++ 编程中创建类和对象。你将定义具有私有数据成员的类,实现公共成员函数,创建具有不同参数的构造函数,编写用于资源清理的析构函数,使用访问说明符,实现类之间的继承,重写基类方法,创建用于访问控制的友元函数,并使用静态成员和方法。这些概念是 C++ 面向对象编程的基础,将为构建更复杂的应用程序奠定坚实的基础。
在本实验中,你将学习如何在 C++ 编程中创建类和对象。你将定义具有私有数据成员的类,实现公共成员函数,创建具有不同参数的构造函数,编写用于资源清理的析构函数,使用访问说明符,实现类之间的继承,重写基类方法,创建用于访问控制的友元函数,并使用静态成员和方法。这些概念是 C++ 面向对象编程的基础,将为构建更复杂的应用程序奠定坚实的基础。
在 C++ 中,类是创建对象的蓝图。它定义了一组属性(数据成员)和方法(成员函数),这些属性和方法将由从该类创建的对象拥有。类有助于组织代码并实现面向对象编程的原则,例如封装、继承和多态。
在 C++ 中定义类的基本语法如下:
class ClassName {
private:
// 私有数据成员
int dataMember1;
std::string dataMember2;
public:
// 公共成员函数
void memberFunction1();
int memberFunction2();
};
C++ 中有三种访问说明符,用于控制类成员的可见性和可访问性:
private
:声明为私有的成员只能在类内部访问。public
:声明为公共的成员可以从类外部访问。protected
:声明为受保护的成员可以在类内部和派生类实例中访问。在本步骤中,你将学习如何在 C++ 中定义具有私有数据成员的类。私有数据成员是面向对象编程中的一个重要概念,有助于封装和保护对象的内部状态。
首先,打开 WebIDE 并导航到 ~/project
目录。创建一个名为 student.cpp
的新文件:
touch ~/project/student.cpp
在 WebIDE 中打开 student.cpp
文件,并添加以下代码以定义一个具有私有数据成员的 Student
类:
#include <iostream>
#include <string>
class Student {
private:
// 私有数据成员
std::string name;
int age;
double gpa;
public:
// 我们将在后续步骤中添加与这些私有成员交互的方法
void displayInfo() {
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "GPA: " << gpa << std::endl;
}
};
int main() {
Student student;
// 注意:我们不能直接访问私有成员
// student.name = "John"; // 这将导致编译错误
student.displayInfo();
return 0;
}
让我们分解关键概念:
私有数据成员:
private:
访问说明符声明数据类型:
std::string name
:存储学生的姓名int age
:存储学生的年龄double gpa
:存储学生的平均绩点封装:
编译程序:
g++ student.cpp -o student
./student
运行程序时的示例输出:
Name:
Age: 0
GPA: 0
关键点:
在本步骤中,你将学习如何在 C++ 中实现公共成员函数。公共成员函数允许对私有数据成员进行受控访问,并提供与类对象交互的方式。
在 WebIDE 中打开 student.cpp
文件,并修改 Student
类以包含公共成员函数:
#include <iostream>
#include <string>
class Student {
private:
std::string name;
int age;
double gpa;
public:
// Setter 方法用于修改私有数据成员
void setName(std::string studentName) {
name = studentName;
}
void setAge(int studentAge) {
if (studentAge > 0 && studentAge < 120) {
age = studentAge;
} else {
std::cout << "Invalid age!" << std::endl;
}
}
void setGPA(double studentGPA) {
if (studentGPA >= 0.0 && studentGPA <= 4.0) {
gpa = studentGPA;
} else {
std::cout << "Invalid GPA!" << std::endl;
}
}
// Getter 方法用于访问私有数据成员
std::string getName() {
return name;
}
int getAge() {
return age;
}
double getGPA() {
return gpa;
}
// 显示方法用于打印学生信息
void displayInfo() {
std::cout << "Student Information:" << std::endl;
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "GPA: " << gpa << std::endl;
}
};
int main() {
Student student;
// 使用公共成员函数设置和获取数据
student.setName("Alice Johnson");
student.setAge(20);
student.setGPA(3.75);
// 显示学生信息
student.displayInfo();
// 演示 getter 方法
std::cout << "\nStudent Name: " << student.getName() << std::endl;
std::cout << "Student Age: " << student.getAge() << std::endl;
std::cout << "Student GPA: " << student.getGPA() << std::endl;
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.75
Student Name: Alice Johnson
Student Age: 20
Student GPA: 3.75
关于公共成员函数的关键点:
在本步骤中,你将学习如何在 C++ 中创建具有不同参数的构造函数。构造函数是一种特殊的成员函数,用于在创建对象时初始化对象。
在 WebIDE 中打开 student.cpp
文件,并修改 Student
类以包含多个构造函数:
#include <iostream>
#include <string>
class Student {
private:
std::string name;
int age;
double gpa;
public:
// 默认构造函数
Student() {
name = "Unknown";
age = 0;
gpa = 0.0;
}
// 带 name 参数的构造函数
Student(std::string studentName) {
name = studentName;
age = 0;
gpa = 0.0;
}
// 带 name 和 age 参数的构造函数
Student(std::string studentName, int studentAge) {
name = studentName;
age = studentAge;
gpa = 0.0;
}
// 带所有参数的完整构造函数
Student(std::string studentName, int studentAge, double studentGPA) {
name = studentName;
age = studentAge;
gpa = studentGPA;
}
// 显示方法用于打印学生信息
void displayInfo() {
std::cout << "Student Information:" << std::endl;
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "GPA: " << gpa << std::endl;
}
};
int main() {
// 使用不同的构造函数
Student student1; // 默认构造函数
Student student2("Alice Johnson"); // 带 name 参数的构造函数
Student student3("Bob Smith", 22); // 带 name 和 age 参数的构造函数
Student student4("Charlie Brown", 20, 3.75); // 完整构造函数
std::cout << "Student 1:" << std::endl;
student1.displayInfo();
std::cout << "\nStudent 2:" << std::endl;
student2.displayInfo();
std::cout << "\nStudent 3:" << std::endl;
student3.displayInfo();
std::cout << "\nStudent 4:" << std::endl;
student4.displayInfo();
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
Student 1:
Student Information:
Name: Unknown
Age: 0
GPA: 0
Student 2:
Student Information:
Name: Alice Johnson
Age: 0
GPA: 0
Student 3:
Student Information:
Name: Bob Smith
Age: 22
GPA: 0
Student 4:
Student Information:
Name: Charlie Brown
Age: 20
GPA: 3.75
关于构造函数的关键点:
在本步骤中,你将学习 C++ 中的析构函数,这是一种特殊的成员函数,负责在对象销毁时清理资源。我们将演示如何编写析构函数,并理解其在内存管理中的重要性。
在 WebIDE 中打开 student.cpp
文件,并修改代码以包含析构函数和动态内存分配:
#include <iostream>
#include <string>
class Student {
private:
std::string name;
int age;
double gpa;
char* dynamicBuffer; // 模拟动态内存分配
public:
// 构造函数
Student() {
name = "Unknown";
age = 0;
gpa = 0.0;
dynamicBuffer = new char[50]; // 分配动态内存
std::cout << "Default Constructor Called" << std::endl;
}
Student(std::string studentName) : name(studentName), age(0), gpa(0.0) {
dynamicBuffer = new char[50];
std::cout << "Parameterized Constructor Called" << std::endl;
}
// 析构函数
~Student() {
// 清理动态分配的内存
delete[] dynamicBuffer;
std::cout << "Destructor Called for " << name << std::endl;
}
void displayInfo() {
std::cout << "Student Information:" << std::endl;
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "GPA: " << gpa << std::endl;
}
};
int main() {
// 演示对象的创建和销毁
{
std::cout << "Creating first student:" << std::endl;
Student student1("Alice Johnson");
student1.displayInfo();
std::cout << "\nCreating second student:" << std::endl;
Student student2("Bob Smith");
student2.displayInfo();
} // 对象在此处超出作用域,析构函数被调用
std::cout << "\nExiting main function" << std::endl;
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
Creating first student:
Parameterized Constructor Called
Student Information:
Name: Alice Johnson
Age: 0
GPA: 0
Creating second student:
Parameterized Constructor Called
Student Information:
Name: Bob Smith
Age: 0
GPA: 0
Destructor Called for Bob Smith
Destructor Called for Alice Johnson
Exiting main function
关于析构函数的关键点:
~
后跟类名定义析构函数的重要特性:
在本步骤中,你将学习 C++ 中的访问说明符,以及它们如何控制类成员的可见性和可访问性。我们将探讨 public、private 和 protected 访问级别之间的区别。
在 WebIDE 中打开 student.cpp
文件,并修改代码以演示访问说明符:
#include <iostream>
#include <string>
class Student {
private:
// 私有成员:只能在类内部访问
std::string name;
int age;
double gpa;
protected:
// 受保护成员:可以在类内部及其派生类中访问
std::string school;
public:
// 公共成员:可以从任何地方访问
Student(std::string studentName, int studentAge, double studentGPA) {
name = studentName;
age = studentAge;
gpa = studentGPA;
school = "Default School";
}
// 公共方法,用于演示对私有成员的访问
void displayInfo() {
std::cout << "Student Information:" << std::endl;
std::cout << "Name: " << name << std::endl; // 访问私有成员
std::cout << "Age: " << age << std::endl;
std::cout << "GPA: " << gpa << std::endl;
std::cout << "School: " << school << std::endl;
}
// 公共方法,用于修改私有成员
void updateGPA(double newGPA) {
if (newGPA >= 0.0 && newGPA <= 4.0) {
gpa = newGPA;
}
}
};
class GraduateStudent : public Student {
public:
GraduateStudent(std::string name, int age, double gpa)
: Student(name, age, gpa) {
// 可以从基类访问受保护的 'school' 成员
school = "Graduate School";
}
void displaySchool() {
std::cout << "School: " << school << std::endl;
}
};
int main() {
Student student("Alice Johnson", 20, 3.75);
student.displayInfo(); // 公共方法访问私有成员
// 取消注释以下行将导致编译错误
// student.name = "John"; // 错误:无法访问私有成员
// student.age = 25; // 错误:无法访问私有成员
student.updateGPA(3.90); // 通过公共方法修改私有成员
student.displayInfo();
GraduateStudent gradStudent("Bob Smith", 25, 3.90);
gradStudent.displayInfo();
gradStudent.displaySchool();
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.75
School: Default School
Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.90
School: Default School
Student Information:
Name: Bob Smith
Age: 25
GPA: 3.90
School: Graduate School
School: Graduate School
关于访问说明符的关键点:
private
:成员只能在同一个类内部访问protected
:成员可以在类内部及其派生类中访问public
:成员可以从任何地方访问在本步骤中,你将学习 C++ 中的继承,这是面向对象编程的一个基本概念,允许基于现有类创建新类。
在 WebIDE 中打开 student.cpp
文件,并修改代码以演示继承:
#include <iostream>
#include <string>
// 基类
class Person {
protected:
std::string name;
int age;
public:
// 构造函数
Person(std::string personName, int personAge) {
name = personName;
age = personAge;
}
// 显示基本信息的方法
void displayInfo() {
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
}
};
// 派生类:Student 继承自 Person
class Student : public Person {
private:
double gpa;
std::string major;
public:
// 调用基类构造函数的构造函数
Student(std::string studentName, int studentAge, double studentGPA, std::string studentMajor)
: Person(studentName, studentAge) {
gpa = studentGPA;
major = studentMajor;
}
// Student 特有的附加方法
void displayStudentInfo() {
// 调用基类方法
displayInfo();
std::cout << "GPA: " << gpa << std::endl;
std::cout << "Major: " << major << std::endl;
}
};
// 另一个派生类:Employee 继承自 Person
class Employee : public Person {
private:
std::string company;
double salary;
public:
// 调用基类构造函数的构造函数
Employee(std::string employeeName, int employeeAge, std::string employeeCompany, double employeeSalary)
: Person(employeeName, employeeAge) {
company = employeeCompany;
salary = employeeSalary;
}
// Employee 特有的附加方法
void displayEmployeeInfo() {
// 调用基类方法
displayInfo();
std::cout << "Company: " << company << std::endl;
std::cout << "Salary: $" << salary << std::endl;
}
};
int main() {
// 创建派生类的对象
Student student("Alice Johnson", 20, 3.75, "Computer Science");
std::cout << "Student Information:" << std::endl;
student.displayStudentInfo();
std::cout << "\n";
Employee employee("Bob Smith", 35, "Tech Corp", 75000.0);
std::cout << "Employee Information:" << std::endl;
employee.displayEmployeeInfo();
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.75
Major: Computer Science
Employee Information:
Name: Bob Smith
Age: 35
Company: Tech Corp
Salary: $75000
关于继承的关键点:
: public BaseClassName
实现继承在本步骤中,你将学习如何在 C++ 中重写基类方法,允许派生类提供从基类继承的方法的自己的实现。
在 WebIDE 中打开 student.cpp
文件,并修改代码以演示方法重写:
#include <iostream>
#include <string>
class Animal {
protected:
std::string name;
public:
Animal(std::string animalName) : name(animalName) {}
// Virtual 关键字允许方法被重写
virtual void makeSound() {
std::cout << "Some generic animal sound" << std::endl;
}
// 用于显示信息的虚方法
virtual void displayInfo() {
std::cout << "Animal Name: " << name << std::endl;
}
};
class Dog : public Animal {
private:
std::string breed;
public:
Dog(std::string dogName, std::string dogBreed)
: Animal(dogName), breed(dogBreed) {}
// 重写 makeSound 方法
void makeSound() override {
std::cout << "Woof! Woof!" << std::endl;
}
// 重写 displayInfo 方法
void displayInfo() override {
// 首先调用基类方法
Animal::displayInfo();
std::cout << "Breed: " << breed << std::endl;
}
};
class Cat : public Animal {
private:
std::string color;
public:
Cat(std::string catName, std::string catColor)
: Animal(catName), color(catColor) {}
// 重写 makeSound 方法
void makeSound() override {
std::cout << "Meow! Meow!" << std::endl;
}
// 重写 displayInfo 方法
void displayInfo() override {
// 首先调用基类方法
Animal::displayInfo();
std::cout << "Color: " << color << std::endl;
}
};
int main() {
// 创建动物对象
Animal genericAnimal("Generic Animal");
Dog myDog("Buddy", "Labrador");
Cat myCat("Whiskers", "Orange");
// 演示多态行为
std::cout << "Generic Animal:" << std::endl;
genericAnimal.displayInfo();
genericAnimal.makeSound();
std::cout << "\nDog:" << std::endl;
myDog.displayInfo();
myDog.makeSound();
std::cout << "\nCat:" << std::endl;
myCat.displayInfo();
myCat.makeSound();
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
Generic Animal:
Animal Name: Generic Animal
Some generic animal sound
Dog:
Animal Name: Buddy
Breed: Labrador
Woof! Woof!
Cat:
Animal Name: Whiskers
Color: Orange
Meow! Meow!
关于方法重写的关键点:
virtual
关键字以启用重写override
关键字以显式重写BaseClass::method()
调用基类方法在本步骤中,你将学习 C++ 中的友元函数,它允许外部函数或其他类访问类的私有和受保护成员。
在 WebIDE 中打开 student.cpp
文件,并修改代码以演示友元函数:
#include <iostream>
#include <string>
class BankAccount {
private:
std::string accountHolder;
double balance;
// 声明友元函数
friend void displayAccountDetails(const BankAccount& account);
friend class AccountManager;
public:
// 构造函数
BankAccount(std::string name, double initialBalance) {
accountHolder = name;
balance = initialBalance;
}
// 存款方法
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
};
// 可以访问私有成员的友元函数
void displayAccountDetails(const BankAccount& account) {
std::cout << "Account Holder: " << account.accountHolder << std::endl;
std::cout << "Current Balance: $" << account.balance << std::endl;
}
// 可以访问私有成员的友元类
class AccountManager {
public:
// 可以访问 BankAccount 私有成员的方法
void transferFunds(BankAccount& from, BankAccount& to, double amount) {
if (from.balance >= amount) {
from.balance -= amount;
to.balance += amount;
std::cout << "Transfer successful!" << std::endl;
} else {
std::cout << "Insufficient funds!" << std::endl;
}
}
};
int main() {
// 创建银行账户
BankAccount account1("Alice Johnson", 1000.0);
BankAccount account2("Bob Smith", 500.0);
// 使用友元函数显示账户详情
std::cout << "Account 1 Details:" << std::endl;
displayAccountDetails(account1);
std::cout << "\nAccount 2 Details:" << std::endl;
displayAccountDetails(account2);
// 使用友元类转账
AccountManager manager;
std::cout << "\nTransferring $200 from Alice to Bob:" << std::endl;
manager.transferFunds(account1, account2, 200.0);
std::cout << "\nUpdated Account Details:" << std::endl;
displayAccountDetails(account1);
displayAccountDetails(account2);
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
Account 1 Details:
Account Holder: Alice Johnson
Current Balance: $1000
Account 2 Details:
Account Holder: Bob Smith
Current Balance: $500
Transferring $200 from Alice to Bob:
Transfer successful!
Updated Account Details:
Account Holder: Alice Johnson
Current Balance: $800
Account Holder: Bob Smith
Current Balance: $700
关于友元函数的关键点:
friend
关键字声明在本步骤中,你将学习 C++ 中的静态成员和方法,它们在类的所有实例之间共享,并且属于类本身而不是单个对象。
在 WebIDE 中打开 student.cpp
文件,并修改代码以演示静态成员和方法:
#include <iostream>
#include <string>
class University {
private:
std::string name;
static int totalStudents; // 静态成员变量
static double totalTuition; // 另一个静态成员变量
public:
// 构造函数
University(std::string universityName) : name(universityName) {}
// 添加学生的方法
void addStudents(int count) {
totalStudents += count;
}
// 添加学费的方法
void addTuition(double amount) {
totalTuition += amount;
}
// 静态方法,用于显示总学生数
static void displayTotalStudents() {
std::cout << "Total Students Across All Universities: "
<< totalStudents << std::endl;
}
// 静态方法,用于显示总学费
static void displayTotalTuition() {
std::cout << "Total Tuition Collected: $"
<< totalTuition << std::endl;
}
// 静态方法,用于计算平均学费
static double calculateAverageTuition() {
return (totalStudents > 0) ?
(totalTuition / totalStudents) : 0.0;
}
};
// 在类外部初始化静态成员变量
int University::totalStudents = 0;
double University::totalTuition = 0.0;
int main() {
// 创建大学对象
University harvard("Harvard University");
University mit("MIT");
University stanford("Stanford University");
// 添加学生和学费
harvard.addStudents(5000);
harvard.addTuition(75000000.0);
mit.addStudents(4500);
mit.addTuition(65000000.0);
stanford.addStudents(4200);
stanford.addTuition(60000000.0);
// 直接在类上调用静态方法
std::cout << "University Statistics:" << std::endl;
University::displayTotalStudents();
University::displayTotalTuition();
// 计算并显示平均学费
std::cout << "Average Tuition per Student: $"
<< University::calculateAverageTuition() << std::endl;
return 0;
}
编译并运行程序:
g++ student.cpp -o student
./student
示例输出:
University Statistics:
Total Students Across All Universities: 13700
Total Tuition Collected: $2e+08
Average Tuition per Student: $14598.5
关于静态成员和方法的关键点:
static
关键字声明在本实验中,你学习了如何定义具有私有数据成员的类,这是面向对象编程中的一个重要概念。私有数据成员有助于封装和保护对象的内部状态。你还了解了公共成员函数的重要性,它们允许对私有数据成员进行受控访问,从而有助于维护数据完整性和控制。此外,你还探索了构造函数、析构函数、访问说明符、继承、方法重写、友元函数以及静态成员和方法的使用,这些都是 C++ 面向对象编程的基本原理。