当前位置: 首页 > article >正文

c++的类和对象(3)

1. Static成员

静态成员是类的一部分,但它们与类的任何特定对象无关。静态成员分为静态数据成员和静态成员函数。

静态数据成员

静态数据成员是与类关联的数据,它们在类的所有对象之间共享。这意味着无论创建了多少个类的对象,静态数据成员只有一个副本。静态数据成员在类的所有实例之外独立存在,并且在程序开始执行之前就已经存在。

以下是静态数据成员的一些特点:

  • 静态数据成员在类声明中使用 static 关键字进行声明。
  • 静态数据成员必须在类的外部进行定义和初始化。
  • 静态数据成员可以通过类名和作用域解析运算符 :: 直接访问,无需创建类的对象。
#include <iostream>

class MyClass {
public:
    static int staticData; // 声明静态数据成员
};

// 定义并初始化静态数据成员
int MyClass::staticData = 10;

int main() {
    // 通过类名直接访问静态数据成员
    std::cout << "Static data member value: " << MyClass::staticData << std::endl;
    
    // 通过对象访问静态数据成员(不推荐,但可行)
    MyClass obj;
    std::cout << "Static data member value via object: " << obj.staticData << std::endl;
    
    return 0;
}

 

静态成员函数

静态成员函数与静态数据成员类似,它们也是类的一部分,但不与类的任何特定对象关联。静态成员函数可以直接访问静态数据成员,但不能直接访问非静态成员,因为它们没有 this 指针。

以下是静态成员函数的一些特点:

  • 静态成员函数在类声明中使用 static 关键字进行声明。
  • 静态成员函数可以在类内部或外部定义。
  • 静态成员函数可以通过类名和作用域解析运算符 :: 直接调用,无需创建类的对象。
#include <iostream>

class MyClass {
public:
    static int staticData; // 声明静态数据成员
    
    // 声明静态成员函数
    static void staticFunction() {
        std::cout << "Static function called. Static data member value: " << staticData << std::endl;
    }
};

int MyClass::staticData = 10;

int main() {
    // 通过类名直接调用静态成员函数
    MyClass::staticFunction();
    
    // 通过对象调用静态成员函数(不推荐,但可行)
    MyClass obj;
    obj.staticFunction();
    
    return 0;
}

 

2. 友元

在C++中,友元(Friend)是一种特殊的访问权限,它允许一个类将其非公有成员(私有或保护)暴露给特定的函数或另一个类,而无需通过类的公有接口。友元可以是函数、类或类的成员函数。

友元函数

友元函数可以是一个普通的非成员函数,也可以是另一个类的成员函数。友元函数不是当前类的成员,但它可以访问该类的所有成员,包括私有成员。

class MyClass {
private:
    int secretValue;

public:
    MyClass() : secretValue(0) {}

    // 声明一个友元函数
    friend void friendFunction(MyClass& obj);
};

// 定义友元函数
void friendFunction(MyClass& obj) {
    // 直接访问MyClass的私有成员
    obj.secretValue = 42;
}

 

友元类

友元类是指一个类被声明为另一个类的友元,这样友元类的所有成员函数都可以访问另一个类的所有成员,包括私有成员。

class AnotherClass;

class MyClass {
private:
    int secretValue;

public:
    MyClass() : secretValue(0) {}

    // 声明AnotherClass为友元类
    friend class AnotherClass;
};

class AnotherClass {
public:
    void accessMyClassSecret(MyClass& obj) {
        // 直接访问MyClass的私有成员
        obj.secretValue = 100;
    }
};

 

3. 内部类

在C++中,内部类(也称为嵌套类或嵌套类型)是在另一个类内部定义的类。内部类可以访问其外部类的私有和保护成员,但外部类不能访问内部类的私有成员。内部类主要用于组织和封装,使得某些功能仅与外部类相关联。

以下是内部类的一些特点和用法:

  1. 访问权限:内部类可以访问其外部类的所有成员,包括私有成员。
  2. 独立性:尽管内部类可以访问外部类的成员,但它是一个独立的类,可以有自己独立的成员和函数。
  3. 作用域:内部类的作用域仅限于其外部类,在外部类之外无法直接访问内部类。
  4. 实例化:要实例化内部类,必须先有一个外部类的实例。
class OuterClass {
private:
    int outerValue;

public:
    OuterClass() : outerValue(0) {}

    class InnerClass { // 内部类的定义
    private:
        int innerValue;

    public:
        InnerClass() : innerValue(0) {}

        void setInnerValue(int value) {
            innerValue = value;
        }

        void setOuterValue(OuterClass& outer, int value) {
            // 内部类可以访问外部类的私有成员
            outer.outerValue = value;
        }
    };

    // 外部类的方法可以返回内部类的实例
    InnerClass getInnerClass() {
        return InnerClass();
    }
};

int main() {
    OuterClass::InnerClass inner; // 错误:不能直接在外部类之外实例化内部类
    OuterClass outer;
    OuterClass::InnerClass inner = outer.getInnerClass(); // 正确:通过外部类的实例来创建内部类的实例
    inner.setInnerValue(10);
    inner.setOuterValue(outer, 20);

    return 0;
}

4. 再次理解封装

封装是面向对象编程(OOP)的四大基本原则之一,与抽象、继承和多态并列。封装的核心思想是将对象的实现细节隐藏起来,只暴露出有限的接口与外界交互。这样做有以下几个目的:

1. 隐藏实现细节

封装允许我们将对象的内部状态和行为隐藏起来,只对外暴露必要的接口。这意味着对象的使用者不需要了解对象内部是如何工作的,只需要知道如何使用对象提供的接口。

2. 保护对象状态

通过封装,我们可以控制对对象内部成员的访问,防止外部直接访问和修改对象的状态,从而保护对象的一致性和完整性。通常,我们会将成员变量设置为私有(private),并通过公共(public)方法来访问和修改这些变量。

3. 提高代码的可维护性

封装使得代码更模块化,每个类都负责管理自己的状态和行为。当需要修改类的内部实现时,只要不改变公共接口,就不会影响到其他使用了该类的代码。这大大提高了代码的可维护性和可扩展性。

4. 降低耦合度

封装通过限制对象的直接交互,减少了对象间的依赖关系,降低了耦合度。低耦合的系统更易于理解和测试,也更容易重用和修改。

封装的具体实现

在C++中,封装通常通过以下方式实现:

  • 访问修饰符:C++提供了三种访问修饰符:publicprotected 和 private

    • public 成员可以被类的外部访问。
    • protected 成员可以被类自身、子类以及友元函数访问。
    • private 成员只能被类自身访问。
  • :类是封装的基本单位,它定义了一个蓝图,用于创建具有特定属性和行为的对象。

  • 构造函数和析构函数:用于初始化和清理对象的状态。

  • 成员函数:提供对内部状态的访问和操作,通常声明为public

class BankAccount {
private:
    double balance; // 私有成员,外部不能直接访问

public:
    BankAccount(double initialBalance) : balance(initialBalance) {}

    void deposit(double amount) { // 公共方法,用于存钱
        if (amount > 0) {
            balance += amount;
        }
    }

    bool withdraw(double amount) { // 公共方法,用于取钱
        if (amount <= balance) {
            balance -= amount;
            return true;
        } else {
            return false;
        }
    }

    double getBalance() const { // 公共方法,用于获取余额
        return balance;
    }
};

int main() {
    BankAccount account(1000.0);
    account.deposit(500.0);
    if (account.withdraw(200.0)) {
        std::cout << "Withdrawal successful. Balance: " << account.getBalance() << std::endl;
    } else {
        std::cout << "Insufficient funds." << std::endl;
    }

    return 0;
}

 


http://www.kler.cn/a/428155.html

相关文章:

  • Docker/K8S
  • deepseek R1的确不错,特别是深度思考模式
  • C++,STL 简介:历史、组成、优势
  • java——继承
  • 【以音频软件FFmpeg为例】通过Python脚本将软件路径添加到Windows系统环境变量中的实现与原理分析
  • 渗透测试之WAF规则触发绕过规则之规则库绕过方式
  • 统计二叉树叶子结点个数
  • Unity3D运行设置物体为预制体
  • 福昕PDF低代码平台
  • Oracle EBS FA 如何打开关闭的资产会计期间?
  • CTF-WEB: 目录穿越与伪协议 [第一届国城杯 signal] 赛后学习笔记
  • 现代C++ 7 初始化
  • 高效开发 Python Web 应用:FastAPI 数据验证与响应体设计
  • 在vue3里使用scss实现简单的换肤功能
  • 3D 生成重建018-LangSplat用文本在3DGS内搜寻你的真爱
  • CCF-GESP 等级考试 2024年12月认证C++三级真题解析
  • MATLAB 直线插点重采样(98)
  • C 语言进阶:突破基础,探索更强大的编程世界
  • 常见面试题之JAVA集合
  • 光伏组件的度电成本如何降低?
  • 解决 Maven 部署中的 Artifact 覆盖问题:实战经验分享20241204
  • Docker--Docker Container(容器)
  • Android显示系统(03)- OpenGL ES - GLSurfaceView的使用
  • Android 调用手机相册,相机功能实现
  • 零基础学安全--Burp Suite验证码识别以及爆破
  • 记一次由docker容器使得服务器cpu占满密码和密钥无法访问bug