c++中有关私有成员的访问问题

在 C++ 中,访问私有成员的权限是严格控制的。以下是关于哪些可以访问私有成员、哪些不可以,以及哪些需要通过友元函数来访问的详细说明:


1. 哪些可以访问私有成员?

以下情况可以访问类的私有成员:

(1)类的成员函数

类的所有成员函数(包括构造函数、析构函数、普通成员函数、运算符重载函数)都可以访问该类的私有成员。

class MyClass {
private:
    int privateVar;

public:
    MyClass(int val) : privateVar(val) {}

    void displayPrivate() {
        // 成员函数可以访问私有成员
        std::cout << "PrivateVar: " << privateVar << std::endl;
    }
};

(2)类的友元函数

友元函数是一个被显式声明为 "友元" 的函数,可以直接访问类的私有成员。它既可以是全局函数,也可以是另一个类的成员函数。

class MyClass {
private:
    int privateVar;

public:
    MyClass(int val) : privateVar(val) {}

    // 声明友元函数
    friend void displayPrivate(const MyClass& obj);
};

// 全局友元函数
void displayPrivate(const MyClass& obj) {
    // 可以直接访问 privateVar
    std::cout << "PrivateVar: " << obj.privateVar << std::endl;
}

(3)类的友元类

一个类可以将另一个类声明为友元类,友元类的所有成员函数都可以访问当前类的私有成员。

class MyClass {
private:
    int privateVar;

public:
    MyClass(int val) : privateVar(val) {}

    // 声明友元类
    friend class FriendClass;
};

class FriendClass {
public:
    void display(const MyClass& obj) {
        // 可以访问 MyClass 的私有成员
        std::cout << "PrivateVar: " << obj.privateVar << std::endl;
    }
};

(4)同类对象之间

同一个类的不同对象可以互相访问私有成员。这是 C++ 的设计特性。

class MyClass {
private:
    int privateVar;

public:
    MyClass(int val) : privateVar(val) {}

    void copyFrom(const MyClass& other) {
        // 可以访问 other 对象的私有成员
        privateVar = other.privateVar;
    }

    void display() const {
        std::cout << "PrivateVar: " << privateVar << std::endl;
    }
};

2. 哪些不能访问私有成员?

以下情况不能直接访问类的私有成员:

(1)普通全局函数

普通的全局函数不能访问类的私有成员,除非它被声明为友元函数。

错误示例:

class MyClass {
private:
    int privateVar;

public:
    MyClass(int val) : privateVar(val) {}
};

void displayPrivate(const MyClass& obj) {
    // 不能访问 privateVar,会编译报错
    // std::cout << "PrivateVar: " << obj.privateVar << std::endl;
}

(2)非友元类

非友元类的成员函数不能访问其他类的私有成员。

错误示例:

class MyClass {
private:
    int privateVar;

public:
    MyClass(int val) : privateVar(val) {}
};

class OtherClass {
public:
    void display(const MyClass& obj) {
        // 不能访问 privateVar,会编译报错
        // std::cout << "PrivateVar: " << obj.privateVar << std::endl;
    }
};

(3)继承的子类

子类不能直接访问父类的私有成员,即使子类继承了父类的所有成员。子类只能通过父类的公有或受保护的接口访问父类的私有成员。

错误示例:

class Parent {
private:
    int privateVar;

public:
    Parent(int val) : privateVar(val) {}
};

class Child : public Parent {
public:
    void display() {
        // 不能直接访问 privateVar,会编译报错
        // std::cout << "PrivateVar: " << privateVar << std::endl;
    }
};

3. 哪些需要友元函数?

当某个非类的成员函数需要访问类的私有成员时,就需要将它声明为友元函数。

具体场景:

  1. 全局函数需要访问私有成员:

    • 例如,全局运算符重载函数(如 operator<<operator>>)。

    示例:

    class MyClass {
    private:
        int privateVar;
    
    public:
        MyClass(int val) : privateVar(val) {}
    
        // 声明友元函数
        friend std::ostream& operator<<(std::ostream& os, const MyClass& obj);
    };
    
    std::ostream& operator<<(std::ostream& os, const MyClass& obj) {
        // 友元函数可以访问 privateVar
        os << "PrivateVar: " << obj.privateVar;
        return os;
    }
    
  2. 非成员函数需要直接访问类的私有成员:

    • 如果你不希望将某些逻辑放在类的成员函数内,而是用全局函数实现,又需要访问私有成员时,就可以使用友元。

4. <<>> 是否可以访问私有成员?

运算符 <<>> 是全局函数,默认情况下不能访问类的私有成员。但是如果它们被声明为类的友元函数,则可以访问。

示例:

#include <iostream>
using namespace std;

class MyClass {
private:
    int privateVar;

public:
    MyClass(int val) : privateVar(val) {}

    // 声明友元函数
    friend ostream& operator<<(ostream& os, const MyClass& obj);
};

ostream& operator<<(ostream& os, const MyClass& obj) {
    // 可以访问 privateVar,因为它是友元
    os << obj.privateVar;
    return os;
}

int main() {
    MyClass obj(42);
    cout << obj << endl;  // 输出:42
    return 0;
}

5. 总结

访问场景是否可以访问私有成员备注
类的成员函数可以成员函数默认可以访问类的私有成员。
类的友元函数可以需要显式声明为友元函数。
类的友元类可以需要显式声明为友元类,友元类的所有成员函数都可以访问。
同类对象可以可以互相访问私有成员。
普通全局函数不可以需要声明为友元函数才能访问。
非友元类不可以非友元类不能访问其他类的私有成员。
子类不可以子类不能直接访问父类的私有成员。
运算符 <<>>不可以除非被声明为友元函数,否则无法访问私有成员。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值