C++入门讲解6:数据的共享与保护核心机制解析与实践

引言

在C++编程中,数据的共享与保护是平衡代码灵活性、安全性和效率的关键。C语言中依赖的全局变量虽能实现数据共享,却破坏了封装性,带来安全隐患。为此,C++提供了静态成员、友元、const修饰、对象指针四大核心机制,既解决了数据共享需求,又通过严格的访问控制保障数据安全。本文将系统解析这些机制的原理、用法及实践场景,结合实例帮助开发者灵活运用。

一、静态成员:类级别的数据共享

静态成员是解决同类对象间数据共享的核心方案,分为静态成员变量和静态成员函数,二者均属于类而非单个对象。

1.1 静态成员变量

  • 核心特性 :用static关键字定义,所有同类对象共享同一份内存空间,值修改对所有对象生效;不随对象创建/销毁分配/释放空间,编译时即开辟内存。

  • 关键用法 :必须在类体外初始化(格式:数据类型 类名::静态成员变量名=初值),无需加static;可通过类名(类名::变量名)或对象名(对象名.变量名)访问。

  • 注意事项:不能通过构造函数参数初始化表初始化。

示例代码

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

class Student {
public:
    static int count; // 静态成员变量:统计学生人数
    string name;
    Student(const char* pN = "no name") : name(pN) {
        count++; // 每创建一个对象,计数+1
    }
    ~Student() {
        count--; // 每销毁一个对象,计数-1
    }
};

int Student::count = 0; // 类外初始化

int main() {
    Student s1("zhangsan");
    cout << "当前学生数:" << Student::count << endl; // 输出1
    Student s2("lisi");
    cout << "当前学生数:" << s2.count << endl; // 输出2
    return 0;
}

1.2 静态成员函数

  • 核心特性 :用static修饰,无this指针,主要用于访问本类静态成员变量。

  • 关键用法:可通过类名或对象名调用;不能直接访问非静态成员变量,需通过"对象名.非静态成员"间接访问。

示例代码

cpp 复制代码
#include <iostream>
#include <cstring>
using namespace std;

class Student {
protected:
    static int count;
    char name[40];
public:
    Student(const char* pN = "no name") {
        strcpy_s(name, pN);
        count++;
    }
    static int number() { // 静态成员函数:返回学生数
        return count; // 直接访问静态成员变量
    }
};

int Student::count = 0;

int main() {
    Student s1("zhangsan"), s2("lisi");
    cout << Student::number() << endl; // 输出2(通过类名调用)
    cout << s1.number() << endl; // 输出2(通过对象名调用)
    return 0;
}

二、友元:突破封装的高效访问

类的封装性限制了私有成员的访问,而友元机制通过"开小孔"的方式,允许特定函数或类直接访问私有成员,兼顾效率与灵活性(需慎用,避免过度破坏封装)。

2.1 友元函数(普通函数)

  • 核心特性 :在类体内用friend声明,类体外按普通函数定义;非成员函数,可直接访问类的所有成员(公有、保护、私有)。

  • 声明格式friend 函数返回类型 函数名(参数表列);

示例:计算两点间距离

cpp 复制代码
#include <iostream>
#include <math.h>
using namespace std;

class Point {
private:
    double x, y;
public:
    Point(double i, double j) : x(i), y(j) {}
    friend double Distance(Point a, Point b); // 友元函数声明
};

// 友元函数定义:直接访问Point的私有成员x、y
double Distance(Point a, Point b) {
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx*dx + dy*dy);
}

int main() {
    Point P1(3.0, 4.0), P2(6.0, 8.0);
    cout << "Distance is " << Distance(P1, P2) << endl; // 输出5
    return 0;
}

2.2 友元成员函数

  • 核心特性:一个类的成员函数被声明为另一个类的友元,可访问该类的所有成员。

  • 注意事项:需提前声明被引用的类(前向声明)。

2.3 友元类

  • 核心特性:若类Y是类X的友元,则Y的所有成员函数都是X的友元函数。

  • 关键规则:友元关系不具有传递性(A是B的友元,B是C的友元,A不一定是C的友元)。

示例代码

cpp 复制代码
#include <iostream>
using namespace std;

class X {
    friend class Y; // Y是X的友元类
private:
    int x;
    static int y;
public:
    void set(int i) { x = i; }
};

int X::y = 10;

class Y {
private:
    X a;
public:
    Y(int i, int j) { a.x = i; X::y = j; } // 直接访问X的私有成员
    void display() { cout << "x=" << a.x << ", y=" << X::y << endl; }
};

int main() {
    X b;
    b.set(5);
    Y c(6, 9);
    c.display(); // 输出x=6, y=9
    return 0;
}

三、常对象与常成员:数据不可篡改的保障

const关键字用于声明常量,在类中可修饰成员变量、成员函数和对象,确保数据在共享时不被篡改。

3.1 常成员变量

  • 核心特性 :用const修饰,必须通过构造函数的成员初始化列表初始化,且终身不可修改。

  • 错误示例 :不能在构造函数体内赋值(A::A(int i){a=i;} 编译报错)。

正确示例

cpp 复制代码
#include <iostream>
using namespace std;

class A {
private:
    const int a; // 常成员变量
public:
    A(int i) : a(i) {} // 初始化列表初始化
    void Print() { cout << a << endl; }
};

int main() {
    A a1(50), a2(30);
    a1.Print(); // 输出50
    a2.Print(); // 输出30
    return 0;
}

3.2 常对象

  • 声明格式类名 const 对象名const 类名 对象名

  • 核心特性:对象的所有成员变量终身不可修改;不能调用普通成员函数(仅允许调用常成员函数和隐含的构造/析构函数)。

3.3 常成员函数

  • 声明格式函数返回类型 函数名(参数表列) const;

  • 核心特性:可访问常对象的成员变量,但不能修改;普通对象和常对象均可调用。

示例代码

cpp 复制代码
#include <iostream>
using namespace std;

class Circle {
private:
    double radius;
public:
    Circle(double r = 0) : radius(r) {}
    double GetR1() const { return radius; } // 常成员函数
    double GetR2() { return radius; } // 普通成员函数
};

int main() {
    const Circle R1(2.5); // 常对象
    Circle R2; // 普通对象
    cout << R1.GetR1() << endl; // 合法:常对象调用常成员函数(输出2.5)
    // cout << R1.GetR2() << endl; // 非法:常对象调用普通成员函数
    cout << R2.GetR2() << endl; // 合法:普通对象调用普通成员函数(输出0)
    return 0;
}

3.4 核心应用关系

成员变量/对象类型 非const成员函数 const成员函数
非const成员变量 可引用、可修改 可引用、不可修改
const成员变量 可引用、不可修改 可引用、不可修改
常对象的成员变量 不可引用、不可修改 可引用、不可修改

四、对象指针:灵活访问与安全控制

对象指针用于指向对象或对象成员,结合const可实现灵活且安全的访问控制,核心包括指向对象的指针、成员指针、this指针等。

4.1 基础对象指针

  • 指向对象的指针类名 *指针名 = &对象名,通过->访问成员(ptr->hour)或(*ptr).成员名

  • 指向对象成员变量的指针数据类型 *指针名 = &对象名.成员变量名

  • 指向对象成员函数的指针 :声明格式返回类型 (类名::*指针名)(参数表列),赋值格式指针名 = &类名::成员函数名

示例代码

cpp 复制代码
#include <iostream>
using namespace std;

class Time {
public:
    int hour, minute, sec;
    Time(int h, int m, int s) : hour(h), minute(m), sec(s) {}
    void get_Time() { cout << hour << ":" << minute << ":" << sec << endl; }
};

int main() {
    Time t1(10, 12, 56);
    Time *p2 = &t1; // 指向对象的指针
    p2->get_Time(); // 输出10:12:56
    
    // 指向成员函数的指针
    void (Time::*p3)() = &Time::get_Time;
    (t1.*p3)(); // 输出10:12:56
    return 0;
}

4.2 this指针

  • 核心作用:隐含在每个非静态成员函数中,指向当前调用函数的对象,用于区分不同对象的成员变量。

  • 本质month = m 等价于 this->month = m,无需显式声明即可使用。

4.3 带const的对象指针

指针类型 声明格式 核心特性
指向对象的常指针 类名 *const 指针名 = &对象名 指针值(指向)不可改,对象内容可改
指向常对象的指针 const 类名 *指针名 指针值可改,对象内容不可通过指针改

应用场景 :作为函数形参,既避免拷贝开销,又保护数据不被修改(如void func(const Time *p))。

4.4 对象的常引用

  • 声明格式const 类名 &引用名 = 对象名

  • 核心优势:作为函数形参时,不产生对象拷贝(高效),且禁止修改实参(安全)。

五、实战练习题与答案

  1. 选择题:一个类的静态成员变量所表示的属性是( ) 答案:A(是类的或对象的属性)

  2. 选择题:类A是类B的友元,类B是类C的友元,则下列说法正确的是( ) 答案:D(以上都不对,友元关系不传递)

  3. 编程题:用友元函数求两数的平方差 答案:

cpp 复制代码
#include<iostream>
using namespace std;
class num {
private:
    float x;
public:
    num(float a) : x(a) {}
    friend float fun(num a, num b) { return a.x*a.x - b.x*b.x; }
};

int main() {
    float x, y;
    cin >> x >> y;
    num n(x), n1(y);
    cout << fun(n, n1) << endl;
    return 0;
}
  1. 选择题:下列程序的输出结果为( )
cpp 复制代码
int i=0;
class A { public: A() {i++;} };
int main() { A a,b[3],*c; c=b; cout&lt;&lt;i&lt;&lt;endl; }

答案:C(4,a是1个对象,b[3]是3个对象,共4个,指针c不创建对象)

六、总结

C++的静态成员、友元、const修饰、对象指针四大机制,从不同维度解决了数据共享与保护的核心需求:静态成员实现类级别的数据共享,友元平衡了封装与访问效率,const确保数据不可篡改,对象指针提供了灵活的访问方式。在实际开发中,需根据场景合理选择:如需同类对象共享数据用静态成员,需高效访问私有成员用友元(慎用),需保护数据不被修改用const,需灵活操作对象用指针(结合const提升安全性)。掌握这些机制,能大幅提升代码的安全性、效率与可维护性。

相关推荐
IT_Octopus2 小时前
Java Protobuf+Zstd 压缩存储Redis实践&问题解决&对比Gzip压缩的大小和性能
java·开发语言·redis
翻斗花园岭第一爆破手2 小时前
flutter3.Container中的decoration
开发语言·前端·javascript
码luffyliu2 小时前
告别 Go 版本混乱:macOS 下工作项目与个人项目版本管理
开发语言·golang·goenv
diegoXie2 小时前
【R】新手向:renv 攻克笔记
开发语言·笔记·r语言
网安_秋刀鱼2 小时前
【java安全】URL链拆解
java·开发语言·安全·web安全·网络安全
ht巷子2 小时前
Qt:容器类
开发语言·c++·qt
云老大TG:@yunlaoda3602 小时前
华为云国际站代理商的DDM的跨境部署调优是如何实现的?
开发语言·数据库·华为云·php
_OP_CHEN2 小时前
【从零开始的Qt开发指南】(十三)Qt 窗口之菜单栏完全攻略:从入门到实战,打造专业级桌面应用菜单系统
开发语言·qt·前端开发·图形化界面·菜单栏·gui开发·qt窗口
superman超哥2 小时前
仓颉协程调度机制深度解析:高并发的秘密武器
c语言·开发语言·c++·python·仓颉