类与对象知识总结+封闭类+const+this指针 C++程序设计与算法笔记总结(三) 北京大学 郭炜(下)

简介: 类与对象知识总结+封闭类+const+this指针 C++程序设计与算法笔记总结(三) 北京大学 郭炜(下)

常量成员函数

如果不希望某个对象的值被改变,则定义该对象的时候可以在前面加 const关键字。

常量成员函数(const member function)是指在类中声明的成员函数,在其声明末尾添加const关键字。常量成员函数承诺不会修改对象的状态,因此它们不能修改类的非静态成员变量,也不能调用非常量成员函数(除非这些成员函数也被声明为常量成员函数)。

常量成员函数对于处理只读操作或者保护数据的完整性很有用,因为它们可以确保在使用常量对象或通过常量引用/指针访问对象时,不会意外地修改对象的状态。

下面是一个示例代码:

class MyClass {
private:
    int data;
public:
    int getValue() const {
        // 这是一个常量成员函数,不能修改成员变量
        return data;
    }
    void setValue(int value) {
        // 非常量成员函数可以修改成员变量
        data = value;
    }
};

在上述示例中,getValue()被声明为常量成员函数,因此它不能修改data成员变量的值。而setValue()是非常量成员函数,可以修改data成员变量。

当你有一个常量对象时,只能调用常量成员函数来访问其成员变量和执行操作。例如:

int main() {
    const MyClass obj;
    int value = obj.getValue();  // 可以调用常量成员函数
    // obj.setValue(10);  // 错误,常量对象无法调用非常量成员函数
    return 0;
}

需要注意的是,在常量成员函数中不能修改成员变量,也不能调用非常量成员函数,除非这些非常量成员函数也被声明为常量成员函数。

常量成员函数在类中声明的成员函数末尾添加const关键字。它们承诺不会修改对象的状态,因此对于只读操作或保护数据完整性很有用。常量成员函数可以在常量对象或通过常量引用/指针访问对象时调用,并且不能修改成员变量或调用非常量成员函数(除非这些成员函数也被声明为常量成员函数)。

当使用常量成员函数时,还需要注意以下几点:

  1. 常量对象调用:常量对象只能调用常量成员函数。这是因为常量对象被视为不可修改的,所以只能使用常量成员函数来访问对象的状态。
  2. 重载:常量成员函数和非常量成员函数可以进行重载。如果有两个成员函数,一个是常量成员函数,另一个是同名的非常量成员函数,它们可以根据调用对象的常量性来区分。
class MyClass {
public:
    int getValue() const {
        // 常量成员函数
        return 10;
    }
    int getValue() {
        // 非常量成员函数
        return 20;
    }
};
int main() {
    const MyClass obj1;
    MyClass obj2;
    int value1 = obj1.getValue();  // 调用常量成员函数
    int value2 = obj2.getValue();  // 调用非常量成员函数
    return 0;
}
  1. 返回类型:常量成员函数可以返回实际值,也可以返回常量引用或指针。如果返回一个非常量类型的实际值,它会被复制到调用者的副本中;如果返回常量引用或指针,则避免了无谓的复制。
  2. mutable关键字:在常量成员函数中,如果希望修改某些成员变量,可以使用mutable关键字来修饰这些成员变量。被mutable修饰的成员变量可以在常量成员函数中被修改。
class MyClass {
private:
    mutable int cacheValue;
public:
    int getValue() const {
        if (cacheValue == 0) {
            // 计算并缓存值
            cacheValue = calculateValue();
        }
        return cacheValue;
    }
    int calculateValue() const {
        // 计算值的逻辑
        return 42;
    }
};

在上述示例中,cacheValue成员变量被声明为mutable,因此可以在常量成员函数中更新它的值。

常量成员函数在保护对象状态的同时,也提供了对只读操作的方便访问。通过合理使用常量成员函数,可以增强代码的安全性和可靠性,并遵循面向对象设计的原则。

常量成员函数是指在类中声明的成员函数末尾添加const关键字。它们只能用于常量对象或通过常量引用/指针访问对象,并且不能修改成员变量或调用非常量成员函数(除非这些成员函数也被声明为常量成员函数)。常量成员函数可以进行重载,返回实际值、常量引用或指针,并且可以使用mutable关键字修饰某些成员变量以在常量成员函数中进行修改。

如果一个成员函数中没有调用非常量成员函数,也没有修改成员变量的值,那么,最好将其写成常量成员函数。

对C++中const的说明

在C++中,const是一个关键字,用于指定对象或变量是只读的,即不可修改。它可以应用于不同的上下文中,包括:

  1. 对象和变量声明:通过在变量或对象的声明前加上const关键字,可以将其标记为只读。这意味着一旦被初始化,就不能再修改该对象或变量的值。
const int x = 10; // 声明一个只读的整数常量x
const MyClass obj; // 声明一个只读的MyClass对象
  1. 函数参数:使用const关键字修饰函数参数,表示该参数在函数内部是只读的,在函数执行过程中不能被修改。
void print(const std::string& str) {
    // 该函数不能修改str的内容
    std::cout << str << std::endl;
}
  1. 成员函数:在成员函数后面添加const关键字,表示该成员函数是一个常量成员函数。常量成员函数承诺不会修改对象的状态,并且只能调用其他常量成员函数或访问类的只读成员变量。
class MyClass {
public:
    void foo() const {
        // 这是一个常量成员函数
        // 不能修改成员变量或调用非常量成员函数
    }
};
  1. 返回类型:const关键字也可以用于指定函数或操作符的返回类型是只读的。
const int calculateValue() {
    // 返回一个只读的整数值
    return 42;
}
const MyClass operator+(const MyClass& obj) const {
    // 返回一个只读的MyClass对象
    // 不能修改当前对象或调用非常量成员函数
}

const关键字对于增强代码的可读性、安全性和可维护性非常有帮助。它可以避免意外的修改,保护数据的完整性,并提供了更好的接口设计和封装性。

需要注意的是,使用const关键字并不意味着该对象或变量在内存中是只读的,而仅仅表示在代码中对其进行修改是不被允许的。

当使用const关键字时,还有一些细节和注意事项需要考虑:

  1. 可以重载非constconst成员函数:在同一个类中,可以同时定义一个非const版本和一个const版本的成员函数。这样,在调用对象为常量或非常量时,编译器会根据调用对象的常量性选择相应的成员函数。
class MyClass {
public:
    void foo() {
        // 非const 版本的成员函数
    }
    void foo() const {
        // const 版本的成员函数
    }
};
  1. 常量对象只能调用常量成员函数:常量对象只能调用常量成员函数,因为常量对象被视为只读对象,不允许修改其状态。但非常量对象可以调用常量成员函数和非常量成员函数。
void someFunction(const MyClass& obj) {
    obj.foo();  // 可以调用常量成员函数
    MyClass nonConstObj;
    nonConstObj.foo();  // 也可以调用非常量成员函数
}
  1. 返回类型是const的影响:如果函数返回类型是const,则返回的值通常不能被修改。
const int getValue() {
    return 42;  // 返回的值是只读的
}
int main() {
    const int value = getValue();
    // value = 10;  // 错误,value是只读的
    return 0;
}
  1. 指针和引用的const:当使用指针或引用时,const关键字可以应用于指针本身或指向的对象。这样可以限制对指针或引用的修改,或者限制被指向的对象的修改。
int x = 10;
const int* ptr = &x;  // 指向常量的指针,不能通过ptr修改x的值
int y = 20;
int* const ref = &y;  // 指向整数的常量指针,不能通过ref修改指针的指向
  1. mutable成员变量:mutable关键字可以用于修饰类的成员变量,它表示该成员变量可以在常量成员函数中被修改。
class MyClass {
private:
    mutable int count;
public:
    void increment() const {
        ++count;  // 在常量成员函数中可以修改mutable成员变量
    }
};

需要注意的是,const关键字应根据需要和语义正确地应用。它可以提高代码的可读性、安全性和可维护性,但也需要谨慎使用以避免过度使用。正确使用const关键字可以帮助捕捉编程错误、保护数据完整性,并提供更好的接口设计和封装性。

当使用const关键字时,还有一些概念和技巧需要了解:

  1. 保证线程安全性:在多线程环境中,常量对象的成员函数是线程安全的。由于常量对象的状态不会被修改,多个线程可以同时访问常量对象的成员函数而无需额外的同步机制。
  2. 常量性转换:常量性可以通过类型转换来进行转换。即可以将非常量对象转换为常量对象进行只读操作。这通过将对象引用或指针的类型从非常量改变为常量来实现。
void func(const MyClass& obj) {
    // 可以接受常量对象作为参数并进行只读操作
}
int main() {
    MyClass obj;
    const MyClass& constRef = obj;  // 将非常量对象转换为常量引用
    const MyClass* constPtr = &obj;  // 将非常量对象的地址转换为常量指针
    return 0;
}
  1. const和函数重载:常量性可以用作函数重载的条件之一。如果一个函数的参数是常量对象或常量引用,那么可以重载该函数以提供对常量对象的特殊处理。
class MyClass {
public:
    void process() {
        // 非const 版本的成员函数
    }
    void process() const {
        // const 版本的成员函数
    }
};
int main() {
    MyClass obj;
    const MyClass constObj;
    obj.process();      // 调用非const版本的process函数
    constObj.process(); // 调用const版本的process函数
    return 0;
}
  1. const修饰符位置:在函数声明中,const关键字可以放在成员函数的后面,也可以放在参数列表的后面。这两种形式的意义是相同的,但通常将const关键字放在函数后面更为常见。
class MyClass {
public:
    void process() const;   // const放在函数后面
    void update() const;    // const放在参数列表后面
};
void MyClass::process() const {
    // const成员函数的实现
}
void MyClass::update() const {
    // const成员函数的实现
}

需要根据具体情况正确使用const关键字。合理使用const可以增强代码的安全性、可读性和可维护性,并帮助捕捉编程错误。它提供了一种约束机制,用于指定只读操作和不会修改对象状态的函数,从而增加了代码的健壮性和可靠性。

常量成员函数的重载

在C++中,常量成员函数可以根据被调用对象的常量性进行重载。这意味着可以定义一个非常量版本和一个常量版本的成员函数,分别用于处理常量对象和非常量对象。

下面是一个示例代码:

class MyClass {
public:
    void foo() {
        // 处理非常量对象的逻辑
        std::cout << "Non-const version" << std::endl;
    }
    void foo() const {
        // 处理常量对象的逻辑
        std::cout << "Const version" << std::endl;
    }
};
int main() {
    MyClass obj1;
    const MyClass obj2;
    obj1.foo();  // 调用非常量版本的foo函数
    obj2.foo();  // 调用常量版本的foo函数
    return 0;
}

在上述示例中,MyClass类定义了两个名为foo()的成员函数,一个是非常量版本,另一个是常量版本。当调用非常量对象obj1foo()函数时,会调用非常量版本;而当调用常量对象obj2foo()函数时,会调用常量版本。

通过使用常量成员函数的重载,可以根据对象的常量性来选择合适的操作方式。这样可以保证对常量对象的只读操作以及非常量对象的修改操作都能得到正确的处理。

需要注意的是,常量成员函数的重载不仅与常量性有关,还与函数的参数类型和数量相关。因此,在进行函数重载时,需要确保函数的签名(包括参数类型、常量性等)是不同的。

总结一下,常量成员函数可以根据对象的常量性进行重载,以提供对常量对象和非常量对象的不同处理。通过合理使用常量成员函数的重载,可以保证对象在不同常量性下得到适当的操作,并增加代码的灵活性和可读性。

mutable成员变量(可以在const成员函数中修改的成员变量)

可以在const成员函数中修改的成员变量

在C++中,mutable关键字用于修饰类的成员变量,它表示该成员变量可以在常量成员函数中被修改,即使这些函数通常是不允许修改对象状态的。

下面是一个示例代码:

class MyClass {
private:
    mutable int count;
public:
    void increment() const {
        ++count;  // 在常量成员函数中可以修改mutable成员变量
    }
};

在上述示例中,count成员变量被声明为mutable,这意味着即使在常量成员函数(如increment())中,也可以对其进行修改。默认情况下,常量成员函数是不允许修改对象的状态的,但使用mutable关键字可以打破这个限制。

mutable关键字适用于那些在实现细节中需要跟踪或缓存信息的成员变量。例如,在某个类中计算并缓存某个值,而不希望每次调用时都重新计算,可以使用mutable来标记该成员变量。

需要注意以下几点:

  • mutable只能应用于非静态成员变量,因为静态成员变量是与类而不是对象相关联的。
  • mutable成员变量的修改仅限于同一对象内部,并不会影响其他对象的状态。
  • 尽管mutable允许在常量成员函数中修改变量,但仍应该谨慎使用。这是因为常量成员函数通常被认为是不会引起对象状态变化的,因此对于需要修改的情况,最好考虑其他可行的设计方案。

总结一下,mutable关键字用于修饰类的成员变量,表示该成员变量可以在常量成员函数中被修改。它在某些情况下提供了更灵活的设计选择,但也应该谨慎使用,以避免滥用导致代码逻辑混乱或违背设计原则。

目录
相关文章
|
11月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
222 2
|
12月前
|
存储 算法 C++
Windows共享文件:探秘C++实现的B树索引算法奇境
在数字化时代,Windows共享文件的高效管理至关重要。B树算法以其自平衡多路搜索特性,在文件索引与存储优化中表现出色。本文探讨B树在Windows共享文件中的应用,通过C++实现具体代码,展示其构建文件索引、优化数据存储的能力,提升文件检索效率。B树通过减少磁盘I/O操作,确保查询高效,为企业和个人提供流畅的文件共享体验。
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
357 15
|
6月前
|
存储 算法
算法入门:专题一:双指针(有效三角形的个数)
给定一个数组,找出能组成三角形的三元组个数。利用“两边之和大于第三边”的性质,先排序,再用双指针优化。固定最大边,左右指针从区间两端向内移动,若两短边之和大于最长边,则中间所有组合均有效,时间复杂度由暴力的O(n³)降至O(n²)。
|
运维 监控 算法
解读 C++ 助力的局域网监控电脑网络连接算法
本文探讨了使用C++语言实现局域网监控电脑中网络连接监控的算法。通过将局域网的拓扑结构建模为图(Graph)数据结构,每台电脑作为顶点,网络连接作为边,可高效管理与监控动态变化的网络连接。文章展示了基于深度优先搜索(DFS)的连通性检测算法,用于判断两节点间是否存在路径,助力故障排查与流量优化。C++的高效性能结合图算法,为保障网络秩序与信息安全提供了坚实基础,未来可进一步优化以应对无线网络等新挑战。
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
11月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
277 17
|
10月前
|
存储 机器学习/深度学习 算法
基于 C++ 的局域网访问控制列表(ACL)实现及局域网限制上网软件算法研究
本文探讨局域网限制上网软件中访问控制列表(ACL)的应用,分析其通过规则匹配管理网络资源访问的核心机制。基于C++实现ACL算法原型,展示其灵活性与安全性。文中强调ACL在企业与教育场景下的重要作用,并提出性能优化及结合机器学习等未来研究方向。
265 4
|
9月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
242 0
|
10月前
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
289 0
下一篇
开通oss服务