C++学习笔记——类作用域和抽象数据类型

本文详细解释了C++中类的作用域,区分了类内和类外作用域,并通过实例展示了如何在类中管理和操作数据。同时介绍了抽象数据类型的概念及其在图书管理系统中的应用。
摘要由CSDN通过智能技术生成

 

目录

一、C++类作用域

类内作用域

类外作用域

二、类作用域案列详细的解释说明

三、抽象数据类型

四、总结

类作用域

抽象数据类型(ADT)

五、图书馆管理系统


一、C++类作用域

在C++中,类作用域是指类定义中声明的标识符(成员变量、成员函数、嵌套类等)所存在的范围。类作用域可以分为两个部分:类内作用域和类外作用域。

  1. 类内作用域

    • 在类定义的内部,成员变量和成员函数的声明和定义都处于类内作用域。
    • 在类内部,可以直接访问类中定义的其他成员,无需使用限定符。
    • 类内部的成员函数可以直接访问类的私有成员。
  2. 类外作用域

    • 在类定义的外部,对类成员的访问需要使用类名和作用域解析运算符(::)来限定。
    • 类外部可以定义成员函数的实现,实现时需要使用类名和作用域解析运算符来指明成员函数所属的类。
    • 类外部的函数可以访问公有成员,但不能直接访问私有成员。

下面是一个示例,展示了类内作用域和类外作用域的使用:

class MyClass {
public:
    int publicMember;   // 公有成员变量

    void memberFunction() {
        privateMember = 10;   // 在类内部可以直接访问私有成员变量
    }

private:
    int privateMember;   // 私有成员变量
};

void MyClass::memberFunction() {
    publicMember = 20;   // 在类外部的成员函数中,使用作用域解析运算符来访问公有成员变量
    privateMember = 30;  // 在类外部的成员函数中,使用作用域解析运算符来访问私有成员变量
}

int main() {
    MyClass obj;
    obj.publicMember = 40;   // 在类外部,使用对象和作用域解析运算符来访问公有成员变量

    return 0;
}

在上述示例中,MyClass类包含一个公有成员变量publicMember和一个私有成员变量privateMember。memberFunction是一个成员函数,它在类内部和类外部都有定义。

在类内部的成员函数中,可以直接访问类的私有成员变量privateMember。在类外部的成员函数中,需要使用作用域解析运算符来访问类的成员变量。在main函数中,我们创建了一个MyClass对象obj,并使用对象和作用域解析运算符来访问公有成员变量publicMember。

通过类作用域的概念,我们可以在类定义中方便地组织和访问成员变量和成员函数,并控制它们的可访问性。

二、类作用域案列详细的解释说明

如何使用类和对象来实现一个学生信息管理系统。该系统可以添加学生信息、显示学生信息和计算学生平均分。

#include <iostream>
#include <string>
using namespace std;

class Student {
private:
    string name;
    int age;
    float score;

public:
    Student(string n, int a, float s) {
        name = n;
        age = a;
        score = s;
    }

    void displayInfo() {
        cout << "Name: " << name << endl;
        cout << "Age: " << age << endl;
        cout << "Score: " << score << endl;
    }

    float getScore() {
        return score;
    }
};

class StudentManager {
private:
    Student* students;
    int size;

public:
    StudentManager(int maxSize) {
        students = new Student[maxSize];
        size = 0;
    }

    ~StudentManager() {
        delete[] students;
    }

    void addStudent(string name, int age, float score) {
        students[size] = Student(name, age, score);
        size++;
    }

    void displayAllStudents() {
        for (int i = 0; i < size; i++) {
            students[i].displayInfo();
            cout << endl;
        }
    }

    float calculateAverageScore() {
        float totalScore = 0;
        for (int i = 0; i < size; i++) {
            totalScore += students[i].getScore();
        }
        return totalScore / size;
    }
};

int main() {
    StudentManager manager(5);

    manager.addStudent("Alice", 20, 85.5);
    manager.addStudent("Bob", 21, 78.2);
    manager.addStudent("Charlie", 19, 92.0);

    cout << "All Students:" << endl;
    manager.displayAllStudents();

    float averageScore = manager.calculateAverageScore();
    cout << "Average Score: " << averageScore << endl;

    return 0;
}

这个案例中,我们定义了两个类:Student和StudentManager。

  • Student类表示一个学生对象,包含了学生的姓名、年龄和成绩。它具有一个构造函数用于初始化学生对象,一个displayInfo函数用于显示学生信息,以及一个getScore函数用于获取学生的成绩。

  • StudentManager类表示一个学生信息管理器,用于添加学生,显示所有学生信息和计算学生平均分。它使用动态内存分配来创建一个可变大小的学生对象数组,并通过addStudent函数将新的学生对象添加到数组中。displayAllStudents函数用于遍历数组并显示每个学生的信息。calculateAverageScore函数用于计算所有学生的平均分。

在主函数main中,我们创建了一个StudentManager对象manager,并使用addStudent函数添加了三个学生信息。然后,我们使用displayAllStudents函数显示所有学生的信息,并使用calculateAverageScore函数计算学生的平均分,并将结果打印出来。

这个案例展示了如何使用类和对象来组织和管理学生信息。通过类和对象的封装特性,我们可以方便地对学生信息进行操作和处理。

三、抽象数据类型

抽象数据类型(Abstract Data Type,ADT)是一种数学模型,用于描述数据对象的逻辑特性和对其进行操作的运算集合。在编程语言中,ADT是一种通过封装数据和操作来定义数据类型的方式,它将数据的表示和操作与实现细节相分离。

ADT包含两个主要组成部分:

  1. 数据对象:数据对象是指具有相同性质和操作的元素的集合。它们可以是简单的数据类型(如整数、浮点数、字符等),也可以是复杂的数据结构(如数组、链表、树等)。

  2. 操作集合:操作集合定义了对数据对象进行的操作或行为。这些操作可以是创建、初始化、访问、修改、删除等。每个操作都有一个名称和一组参数,用于操作数据对象。

ADT的设计目标是将数据类型的实现细节隐藏起来,使用户只能通过操作集合来访问和操作数据对象,而无需关心具体的实现细节。这样可以提高代码的可读性、可维护性和可重用性。

举个例子,我们可以以栈(Stack)为例来说明ADT的概念:

class Stack {
private:
    int* elements;
    int top;
    int maxSize;

public:
    Stack(int size) {
        elements = new int[size];
        top = -1;
        maxSize = size;
    }

    ~Stack() {
        delete[] elements;
    }

    void push(int value) {
        if (top < maxSize - 1) {
            top++;
            elements[top] = value;
        }
    }

    int pop() {
        if (top >= 0) {
            int value = elements[top];
            top--;
            return value;
        }
        return -1;
    }

    bool isEmpty() {
        return top == -1;
    }
};

在这个例子中,我们定义了一个抽象数据类型Stack,它表示一个栈数据结构。栈是一种具有后进先出(LIFO)特性的数据结构,可以使用push操作将元素压入栈顶,使用pop操作从栈顶取出元素。

在Stack类中,我们使用一个动态分配的整型数组elements来存储栈中的元素,使用变量top来标记栈顶位置,使用变量maxSize来表示栈的最大容量。通过push函数向栈中压入元素,通过pop函数从栈中取出元素,通过isEmpty函数判断栈是否为空。

通过这个例子,我们可以看到,使用抽象数据类型可以将数据结构的实现细节隐藏起来,用户只需关心如何使用操作集合来操作数据对象,而无需关心底层的实现细节。这样可以提高代码的可读性和可维护性,同时也方便了代码的重用和扩展。

四、总结

总结一下类作用域和抽象数据类型的主要内容

  1. 类作用域

    • 类作用域是指在类定义中声明的变量、函数和类型的可见性范围。
    • 在类作用域内部,成员变量和成员函数可以直接访问,无需使用任何限定符。
    • 类作用域可以通过访问修饰符(public、private、protected)来控制成员的可访问性。
    • 类作用域内的成员可以被类的对象访问和操作。
  2. 抽象数据类型(ADT)

    • ADT是一种通过封装数据和操作来定义数据类型的方式,将数据的表示和操作与实现细节相分离。
    • ADT包含一个数据对象和一组操作集合,其中数据对象是具有相同性质和操作的元素的集合,操作集合定义了对数据对象进行的操作或行为。
    • ADT的设计目标是隐藏数据类型的实现细节,使用户只能通过操作集合来访问和操作数据对象,而无需关心具体的实现细节。
    • ADT可以提高代码的可读性、可维护性和可重用性,同时也帮助管理复杂的数据结构和操作。

类作用域和抽象数据类型是面向对象编程中的重要概念。类作用域帮助管理类内部的成员访问和可见性,而抽象数据类型则提供了一种将数据和操作封装在一起的方式,使用户能够以更高层次的抽象来处理数据对象。这些概念在软件开发中起到了重要的作用,可以提高代码的可维护性、可扩展性和可重用性。

五、图书馆管理系统

一个经典的案例是实现一个图书管理系统。这个系统可以用来管理图书馆的图书信息,包括图书的名称、作者、出版日期等信息,并提供借阅和归还图书的功能。

下面是一个简化版本的图书管理系统的示例:

#include <iostream>
#include <string>
#include <vector>

class Book {
private:
    std::string title;
    std::string author;
    int publicationYear;
    bool borrowed;

public:
    Book(const std::string& bookTitle, const std::string& bookAuthor, int year)
        : title(bookTitle), author(bookAuthor), publicationYear(year), borrowed(false) {}

    std::string getTitle() const {
        return title;
    }

    std::string getAuthor() const {
        return author;
    }

    int getPublicationYear() const {
        return publicationYear;
    }

    bool isBorrowed() const {
        return borrowed;
    }

    void borrowBook() {
        if (!borrowed) {
            borrowed = true;
            std::cout << "Successfully borrowed the book: " << title << std::endl;
        } else {
            std::cout << "The book is already borrowed." << std::endl;
        }
    }

    void returnBook() {
        if (borrowed) {
            borrowed = false;
            std::cout << "Successfully returned the book: " << title << std::endl;
        } else {
            std::cout << "The book is not currently borrowed." << std::endl;
        }
    }
};

class Library {
private:
    std::vector<Book> books;

public:
    void addBook(const Book& book) {
        books.push_back(book);
    }

    void listBooks() const {
        for (const auto& book : books) {
            std::cout << "Title: " << book.getTitle() << ", Author: " << book.getAuthor()
                      << ", Publication Year: " << book.getPublicationYear()
                      << ", Borrowed: " << (book.isBorrowed() ? "Yes" : "No") << std::endl;
        }
    }

    void borrowBook(const std::string& title) {
        for (auto& book : books) {
            if (book.getTitle() == title) {
                book.borrowBook();
                return;
            }
        }

        std::cout << "The book '" << title << "' is not available in the library." << std::endl;
    }

    void returnBook(const std::string& title) {
        for (auto& book : books) {
            if (book.getTitle() == title) {
                book.returnBook();
                return;
            }
        }

        std::cout << "The book '" << title << "' is not available in the library." << std::endl;
    }
};

int main() {
    Library library;

    Book book1("The Great Gatsby", "F. Scott Fitzgerald", 1925);
    Book book2("To Kill a Mockingbird", "Harper Lee", 1960);
    Book book3("1984", "George Orwell", 1949);

    library.addBook(book1);
    library.addBook(book2);
    library.addBook(book3);

    library.listBooks();

    library.borrowBook("To Kill a Mockingbird");
    library.borrowBook("The Great Gatsby");

    library.listBooks();

    library.returnBook("To Kill a Mockingbird");

    library.listBooks();

    return 0;
}

这个案例中,我们定义了两个类:Book和Library。Book类表示一本书,包含了书的相关信息和借阅状态。Library类表示图书馆,包含了图书的集合和相关的操作方法。

在主函数中,我们创建了几本书,并将它们添加到图书馆中。然后,我们展示了图书馆中的所有书籍,并进行了一些借阅和归还操作。

这个案例虽然简化了实际的图书管理系统,但是它演示了如何使用类来管理对象的数据和行为,并展示了类之间的交互。这个案例可以作为一个起点,可以根据需求进一步扩展和完善图书管理系统的功能。

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tech行者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值