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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 类与对象知识总结+封闭类+const+this指针 C++程序设计与算法笔记总结(三) 北京大学 郭炜(中)

如何访问静态成员

如何访问静态成员

1) 类名::成员名
CRectangle::PrintTotal();
1) 对象名.成员名
CRectangle r; r.PrintTotal();
1) 指针->成员名
CRectangle * p = &r; p->PrintTotal();
1) 引用.成员名
CRectangle & ref = r; int n = ref.nTotalNumber; 

要访问静态成员变量和静态成员函数,可以使用类名和作用域解析运算符来进行访问。

  1. 访问静态成员变量:使用类名和作用域解析运算符::来访问静态成员变量。例如,如果有一个名为MyClass的类,并且该类包含一个静态成员变量staticVar,可以通过MyClass::staticVar来访问它。
class MyClass {
public:
    static int staticVar;
};
int MyClass::staticVar = 10; // 初始化静态成员变量
int main() {
    int value = MyClass::staticVar; // 访问静态成员变量
    return 0;
}
  1. 调用静态成员函数:同样地,使用类名和作用域解析运算符::来调用静态成员函数。例如,如果有一个名为MyClass的类,并且该类包含一个静态成员函数staticFunc,可以通过MyClass::staticFunc()来调用它。
class MyClass {
public:
    static void staticFunc() {
        // 静态成员函数的实现
    }
};
int main() {
    MyClass::staticFunc(); // 调用静态成员函数
    return 0;
}

需要注意的是,静态成员变量和静态成员函数在编译期间就已经存在,无需实例化对象即可访问和调用。它们不依赖于特定对象的状态,因此可以直接通过类名进行访问。

总结一下,要访问静态成员变量和调用静态成员函数,使用类名和作用域解析运算符::来进行访问和调用。静态成员变量和静态成员函数在编译期间就已经存在,并且无需实例化对象即可访问和调用。

除了使用类名和作用域解析运算符来访问静态成员,还有其他几种方式可以进行访问。

  1. 通过对象访问静态成员:虽然静态成员是与类关联而不是与对象关联的,但实际上也可以通过对象来访问静态成员。这是因为在编译器中,对象会自动转换为对应的类类型指针,从而可以使用指针来访问静态成员。
class MyClass {
public:
    static int staticVar;
};
int MyClass::staticVar = 10; // 初始化静态成员变量
int main() {
    MyClass obj;
    int value = obj.staticVar; // 通过对象访问静态成员变量
    return 0;
}

尽管可以通过对象访问静态成员,但这样做并不推荐,因为它可能会造成混淆,并且容易让人误以为静态成员是与对象相关联的。

2. 通过指针访问静态成员:与使用对象类似,可以使用指向类类型的指针来访问静态成员。这里需要注意的是,由于静态成员不依赖于特定对象的状态,可以直接通过类名来访问,无需通过指针间接访问。

class MyClass {
public:
    static int staticVar;
};
int MyClass::staticVar = 10; // 初始化静态成员变量
int main() {
    MyClass* ptr = nullptr;
    int value = ptr->staticVar; // 通过指针访问静态成员变量
    return 0;
}

需要注意的是,在使用对象或指针访问静态成员时,静态成员的访问权限仍然适用。如果静态成员是私有的,则无法通过对象或指针进行访问。

除了使用类名和作用域解析运算符来访问静态成员外,还可以通过对象或指针来访问。但这些方式并不推荐,因为静态成员是与类关联而不是与对象关联的。最佳实践是直接使用类名来访问静态成员,以确保清晰明确。

静态成员变量本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。

静态成员函数本质上是全局函数。

设置静态成员这种机制的目的是将和某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解。

注意事项

在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。

void CRectangle::PrintTotal()
{
cout << w << "," << nTotalNumber << "," << 
nTotalArea << endl; //wrong
}

示例:

确实,你可以使用静态成员变量和静态成员函数来封装总数和总面积,并确保在整个程序中只有一个副本。

下面是一个示例代码:

class Rectangle {
private:
    int width;
    int height;
    static int totalCount;
    static int totalArea;
public:
    Rectangle(int w, int h) : width(w), height(h) {
        totalCount++;
        totalArea += width * height;
    }
    static int getTotalCount() {
        return totalCount;
    }
    static int getTotalArea() {
        return totalArea;
    }
};
int Rectangle::totalCount = 0;
int Rectangle::totalArea = 0;
int main() {
    Rectangle rect1(10, 20);
    Rectangle rect2(5, 15);
    int count = Rectangle::getTotalCount();
    int area = Rectangle::getTotalArea();
    return 0;
}

在上述示例中,我们定义了一个Rectangle类,其中包含私有的width和height成员变量,以及静态的totalCount和totalArea成员变量。构造函数会在创建每个矩形对象时自动增加totalCount,并将面积累加到totalArea中。通过静态成员函数getTotalCount()和getTotalArea(),我们可以获取整个程序中所有矩形的总数和总面积。

使用静态成员封装这些变量的好处是,它们与类相关联,并且在整个程序中只有一个副本。这样可以更容易地理解和维护代码,确保数据的一致性。

需要注意的是,静态成员变量和静态成员函数可以在类的定义中声明,在类外部初始化。并且它们不依赖于特定对象的状态,因此可以直接通过类名来访问。

总结一下,使用静态成员变量和静态成员函数可以封装总数和总面积,并确保在整个程序中只有一个副本。这样可以更容易地理解和维护代码,同时保持数据的一致性。

成员对象和封闭类

在C++中,成员对象和封闭类是一种关系,其中封闭类包含一个成员对象作为其成员之一。这种关系可以通过将另一个类的对象声明为封闭类的成员变量来实现。

通过使用成员对象,封闭类可以利用其他类提供的功能,并且可以访问成员对象的成员变量和成员函数。这样,封闭类可以将其他类的功能组合在一起,以实现更复杂的行为。

上例中,如果 CCar类不定义构造函数, 则下面的语句会编译出错:

CCar car;

因为编译器不明白 car.tyre该如何初始化。car.engine 的初始化没问题,用默认构造函数即可。

任何生成封闭类对象的语句,都要让编译器明白,对象中的成员对象,是如何初始化的。

具体的做法就是:通过封闭类的构造函数的初始化列表。

成员对象初始化列表中的参数可以是任意复杂的表达式,可以包括函数,变量,只要表达式中的函数或变量有定义就行。

下面是一个示例代码:

class Engine {
public:
    void start() {
        // 引擎启动逻辑
    }
};
class Car {
private:
    Engine engine;
public:
    void startCar() {
        engine.start();
        // 其他汽车启动逻辑
    }
};

在上述示例中,Car类包含一个Engine对象作为其成员变量。通过将Engine对象声明为Car类的成员变量,Car类可以使用Engine类提供的start()函数来启动引擎。在Car类的startCar()函数中,我们可以调用engine对象的start()函数来启动引擎,并执行其他与汽车启动相关的逻辑。

使用成员对象和封闭类的好处是可以实现代码的模块化和可重用性。封闭类可以通过成员对象来获取其他类的功能,并将其组合在一起,从而实现更高级的行为。

需要注意的是,在封闭类的构造函数中,成员对象的构造函数也会被调用。类似地,在封闭类的析构函数中,成员对象的析构函数也会被调用。这确保了成员对象在封闭类的生命周期内正确地进行构造和销毁。

总结一下,成员对象和封闭类是一种关系,其中封闭类包含其他类的对象作为其成员之一。这种关系允许封闭类利用其他类提供的功能,并通过组合来实现更复杂的行为。使用成员对象和封闭类可以实现代码的模块化和可重用性。

在C++中,成员对象和封闭类是一种关系,其中封闭类包含一个成员对象作为其成员之一。这种关系可以通过将另一个类的对象声明为封闭类的成员变量来实现。

通过使用成员对象,封闭类可以利用其他类提供的功能,并且可以访问成员对象的成员变量和成员函数。这样,封闭类可以将其他类的功能组合在一起,以实现更复杂的行为。

下面是一个示例代码:

class Engine {
public:
    void start() {
        // 引擎启动逻辑
    }
};
class Car {
private:
    Engine engine;
public:
    void startCar() {
        engine.start();
        // 其他汽车启动逻辑
    }
};

在上述示例中,Car类包含一个Engine对象作为其成员变量。通过将Engine对象声明为Car类的成员变量,Car类可以使用Engine类提供的start()函数来启动引擎。在Car类的startCar()函数中,我们可以调用engine对象的start()函数来启动引擎,并执行其他与汽车启动相关的逻辑。

使用成员对象和封闭类的好处是可以实现代码的模块化和可重用性。封闭类可以通过成员对象来获取其他类的功能,并将其组合在一起,从而实现更高级的行为。

在封闭类的构造函数中,成员对象的构造函数也会被调用。类似地,在封闭类的析构函数中,成员对象的析构函数也会被调用。这确保了成员对象在封闭类的生命周期内正确地进行构造和销毁。

成员对象和封闭类是一种关系,其中封闭类包含其他类的对象作为其成员之一。这种关系允许封闭类利用其他类提供的功能,并通过组合来实现更复杂的行为。使用成员对象和封闭类可以实现代码的模块化和可重用性。

封闭类构造函数和析构函数的执行顺序

封闭类对象生成时,先执行所有对象成员的构造函数,然后才执行封闭类的构造函数。

对象成员的构造函数调用次序和对象成员在类中的说明次序一致,与它们在成员初始化列表中出现的次序无关。

当封闭类的对象消亡时,先执行封闭类的析构函数,然后再执行成员对象的析构函数。次序和构造函数的调用次序相反。

封闭类的复制构造函数用于创建一个新的对象,该对象是从现有的同类型对象进行复制而来。在复制构造函数中,通常需要对成员对象进行深拷贝,以确保新对象和原对象拥有独立的资源。

下面是一个示例代码:

class MyClass {
private:
    int* data;
public:
    MyClass(const MyClass& other) {
        // 执行深拷贝操作
        data = new int(*other.data);
    }
    // 其他成员函数和构造函数的实现
    ~MyClass() {
        delete data;
    }
};

在上述示例中,我们定义了一个名为MyClass的封闭类,并在其中包含一个动态分配的int类型数据成员data。在复制构造函数中,我们使用new关键字创建了一个新的int对象,并将其初始化为原对象中data指针指向的值的副本。这样可以确保新对象和原对象具有独立的资源。

需要注意的是,在复制构造函数中,还需要处理其他成员变量的复制,以确保新对象拥有与原对象相同的状态。

此外,当定义自定义的复制构造函数时,还应该考虑以下几点:

  1. 深拷贝 vs 浅拷贝:如果成员对象本身包含指针或动态分配的内存,复制构造函数应该执行深拷贝,即创建新的资源副本。如果成员对象是只读或不可变的,可以使用浅拷贝。
  2. 异常安全性:在执行深拷贝操作时,应保证异常安全性。即使在复制过程中抛出了异常,也要正确处理资源的释放,以防止内存泄漏或资源泄漏。
  3. 赋值运算符重载:除了复制构造函数外,还应该重载赋值运算符(=)以支持对象的赋值操作。赋值运算符重载函数的实现与复制构造函数类似。

总结一下,封闭类的复制构造函数用于创建一个新的对象,并以深拷贝的方式复制成员对象和资源。需要对每个成员变量进行适当的复制操作,以确保新对象和原对象具有独立的状态。同时,还应考虑异常安全性和赋值运算符重载的实现。

友元(friends)

友元分为友元函数和友元类两种

友元(friends)是C++中一种特殊的访问权限,它允许某个类或函数访问另一个类的私有成员。通过将一个类或函数声明为另一个类的友元,可以在友元类或函数中直接访问该类的私有成员。

下面是一个示例代码:

class MyClass {
private:
    int privateData;
public:
    MyClass() : privateData(0) {}
    friend class FriendClass;  // 声明FriendClass为MyClass的友元
    void printPrivateData() {
        std::cout << privateData << std::endl;
    }
};
class FriendClass {
public:
    void modifyPrivateData(MyClass& obj, int newData) {
        obj.privateData = newData; // 在FriendClass中直接访问MyClass的私有成员
    }
};
int main() {
    MyClass obj;
    FriendClass friendObj;
    friendObj.modifyPrivateData(obj, 42);
    obj.printPrivateData(); // 输出: 42
    return 0;
}

在上述示例中,我们声明了一个名为MyClass的类,并声明了一个名为FriendClass的类为其友元。在FriendClass中,我们可以直接访问MyClass的私有成员privateData,并进行修改。这得益于FriendClass被声明为MyClass的友元。

需要注意的是,友元关系是单向的,即如果类A声明类B为友元,那么类A的成员函数可以访问类B的私有成员,但类B的成员函数不能自动访问类A的私有成员。如果需要相互访问,需要进行相应的声明。

此外,友元关系是一种破坏封装性的机制,因此应该谨慎使用。合理使用友元可以提供对类的特定部分的访问权限,使得某些操作更方便,但也可能导致代码的可维护性和安全性降低。

总结一下,C++中的友元机制允许一个类或函数访问另一个类的私有成员。通过将一个类或函数声明为另一个类的友元,在友元类或函数中可以直接访问被授权类的私有成员。友元关系是单向的,并且应该谨慎使用,以避免破坏封装性和引入安全问题。

**友元关系可以分为两种类型:友元函数(friend function)和友元类(friend class)。

  1. 友元函数:友元函数是在一个类中声明的非成员函数,并且被声明为该类的友元。这意味着友元函数可以直接访问该类的私有成员。通过友元函数,可以将某个外部函数与类建立关联,以便在实现特殊操作或提供其他功能时访问类的私有成员。
class MyClass {
private:
    int privateData;
public:
    friend void friendFunction(MyClass& obj);  // 声明friendFunction为MyClass的友元
    // 其他成员函数和构造函数的实现
};
void friendFunction(MyClass& obj) {
    obj.privateData = 42;  // 在友元函数中直接访问MyClass的私有成员
}
  1. 友元类:友元类是在一个类中声明的另一个类,并且被声明为该类的友元。这意味着友元类的成员函数可以直接访问该类的私有成员。通过友元类,可以使得一个类能够访问另一个类的私有成员,从而实现更灵活的设计和组合。
class FriendClass {
public:
    void modifyPrivateData(MyClass& obj) {
        obj.privateData = 42;  // 在FriendClass中直接访问MyClass的私有成员
    }
};
class MyClass {
private:
    int privateData;
public:
    friend class FriendClass;  // 声明FriendClass为MyClass的友元
    // 其他成员函数和构造函数的实现
};

需要注意的是,友元关系应该被谨慎使用,以确保封装性和安全性。友元关系的目的是为了提供灵活性和特殊情况下的访问权限,但过度使用可能会导致代码不易理解和维护。在设计中,应仔细考虑是否真正需要友元关系,并根据具体需求和设计原则进行选择。

友元类之间的关系不能传递,不能继承。

当使用友元关系时,还需要注意以下几点:

  1. 友元的范围:友元关系是通过类而不是对象来建立的。一个类的所有对象都可以访问另一个类的私有成员,只要这个类在其声明中将另一个类声明为友元。
  2. 友元的传递性:如果类A声明类B为友元,同时类B声明类C为友元,那么类A的成员函数也可以访问类C的私有成员。这种传递性的友元关系使得在复杂的代码结构中,可以通过一系列的友元声明来实现灵活的访问权限。
  3. 函数作为友元:除了类之间可以建立友元关系外,函数也可以被声明为类的友元。这样,该函数就可以直接访问该类的私有成员。函数作为友元可以用于提供特定操作或算法所需的访问权限。
  4. 友元关系不具备继承性:友元关系不会被继承。即使派生类继承了基类的友元关系,它自己并不具备对基类私有成员的访问权限。
  5. 封装和信息隐藏:友元关系破坏了封装性,因此应谨慎使用。友元关系通常用于某些特殊的情况下,例如需要访问私有成员进行优化或实现特殊的操作。

需要明智地使用友元关系,以平衡代码的封装性和灵活性。友元机制可以提供对类的私有成员的访问权限,但也可能导致代码的可维护性和安全性降低。因此,应该仔细考虑并评估在特定情况下使用友元关系的利弊,并确保其使用符合设计原则和需求。

目录
相关文章
|
1月前
|
运维 监控 算法
解读 C++ 助力的局域网监控电脑网络连接算法
本文探讨了使用C++语言实现局域网监控电脑中网络连接监控的算法。通过将局域网的拓扑结构建模为图(Graph)数据结构,每台电脑作为顶点,网络连接作为边,可高效管理与监控动态变化的网络连接。文章展示了基于深度优先搜索(DFS)的连通性检测算法,用于判断两节点间是否存在路径,助力故障排查与流量优化。C++的高效性能结合图算法,为保障网络秩序与信息安全提供了坚实基础,未来可进一步优化以应对无线网络等新挑战。
|
1月前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
72 15
|
1月前
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
2天前
|
存储 算法 C++
Windows共享文件:探秘C++实现的B树索引算法奇境
在数字化时代,Windows共享文件的高效管理至关重要。B树算法以其自平衡多路搜索特性,在文件索引与存储优化中表现出色。本文探讨B树在Windows共享文件中的应用,通过C++实现具体代码,展示其构建文件索引、优化数据存储的能力,提升文件检索效率。B树通过减少磁盘I/O操作,确保查询高效,为企业和个人提供流畅的文件共享体验。
|
16天前
|
存储 监控 算法
基于 C++ 哈希表算法的局域网如何监控电脑技术解析
当代数字化办公与生活环境中,局域网的广泛应用极大地提升了信息交互的效率与便捷性。然而,出于网络安全管理、资源合理分配以及合规性要求等多方面的考量,对局域网内计算机进行有效监控成为一项至关重要的任务。实现局域网内计算机监控,涉及多种数据结构与算法的运用。本文聚焦于 C++ 编程语言中的哈希表算法,深入探讨其在局域网计算机监控场景中的应用,并通过详尽的代码示例进行阐释。
37 4
|
26天前
|
存储 算法 安全
企业员工数据泄露防范策略:基于 C++ 语言的布隆过滤器算法剖析[如何防止员工泄密]
企业运营过程中,防范员工泄密是信息安全领域的核心议题。员工泄密可能致使企业核心数据、商业机密等关键资产的流失,进而给企业造成严重损失。为应对这一挑战,借助恰当的数据结构与算法成为强化信息防护的有效路径。本文专注于 C++ 语言中的布隆过滤器算法,深入探究其在防范员工泄密场景中的应用。
41 8
|
2月前
|
存储 监控 算法
员工屏幕监控系统之 C++ 图像差分算法
在现代企业管理中,员工屏幕监控系统至关重要。本文探讨了其中常用的图像差分算法,该算法通过比较相邻两帧图像的像素差异,检测屏幕内容变化,如应用程序切换等。文中提供了C++实现代码,并介绍了其在实时监控、异常行为检测和数据压缩等方面的应用,展示了其实现简单、效率高的特点。
77 15
|
2月前
|
算法 Serverless 数据处理
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
79 12
|
2月前
|
存储 监控 算法
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
在数字化办公时代,公司监控上网软件成为企业管理网络资源和保障信息安全的关键工具。本文深入剖析C++中的链表数据结构及其在该软件中的应用。链表通过节点存储网络访问记录,具备高效插入、删除操作及节省内存的优势,助力企业实时追踪员工上网行为,提升运营效率并降低安全风险。示例代码展示了如何用C++实现链表记录上网行为,并模拟发送至服务器。链表为公司监控上网软件提供了灵活高效的数据管理方式,但实际开发还需考虑安全性、隐私保护等多方面因素。
40 0
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
|
3月前
|
负载均衡 算法 安全
探秘:基于 C++ 的局域网电脑控制软件自适应指令分发算法
在现代企业信息化架构中,局域网电脑控制软件如同“指挥官”,通过自适应指令分发算法动态调整指令发送节奏与数据量,确保不同性能的终端设备高效运行。基于C++语言,利用套接字实现稳定连接和线程同步管理,结合实时状态反馈,优化指令分发策略,提升整体管控效率,保障网络稳定,助力数字化办公。
90 19

热门文章

最新文章

下一篇
oss创建bucket