温习C++友元

友元函数和友元类

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
为什么要使用友元函数
运算符重载的某些场合需要使用友元。(略)
两个类要共享数据:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。

友元函数的优缺点
优点:方便
缺点:友元函数破环了封装机制。不得已的情况下才使用友元函数

友元函数

class A
{
public:
    A(int _a):a(_a){};
    A() = default;
    friend int getA_a(A &_classA);//友元函数
    friend std::ostream& operator <<(std::ostream &os,const A& a);
    friend std::istream& operator >>(std::istream &in,A& a);
    int getA_a(){
        std::cout <<"调用类成员函数"<< std::endl;
        return this->a;
    }
private:
    int a;
};

int getA_a(A &_classA){
    std::cout <<"调用友元函数"<< std::endl;
    return _classA.a;//通过对象名访问私有变量
}
std::ostream& operator <<(std::ostream &os,const A& a){
    os << a.a;
    return os;
}
std::istream& operator >>(std::istream& in,A& a){
    in >> a.a;
    return in;
}

友元类

// 友元类主要为了提高效率,同时避免public 过于开放
class C;
class B{
public:
    B(int _b):b(_b){}
    void set(int v){
        b += v / 3 + v / 4;
    }
    friend class C;
    void set_c(std::shared_ptr<C> c){
        c_ptrl = c;
    }
private:
    int b;
    std::shared_ptr<class C> c_ptrl;
};
class C{
public:
    void set_c(B b){
        this->c = 2 * get_b(b);
    }
    void get_bc(B b){
        std::cout <<get_b(b) <<"   "<<this->c<< std::endl;
    }
private:
    int c;
    int get_b(B b){
        return b.b;
    }
};

测试

int main(int argc, char* argv[])
{
	// test friend function
    A _classA(3);
    std::cout << getA_a(_classA)<<std::endl;;//友元函数只是普通函数,可以在任意地方调用
    std::cout << _classA.getA_a() << std::endl;
    A a;
    std::cin >> a;
    std::cout << a << std::endl;
    
    // test friend class
    B b{0};
    std::shared_ptr<C> c(new C{});
    b.set_c(c);
    using namespace std::chrono_literals;
    auto RUN_B = [](B *b){
        for(int i = 0; i < 10000; i++){
            b->set(i);
            std::this_thread::sleep_for(10ms);
        }
    };
    std::thread t1(RUN_B,&b);
    auto RUN_C = [](std::shared_ptr<C> c,B &b){
        int i = 0;
        while(true){
            c->set_c(b);
            std::cout <<i++<<"  :  ";c->get_bc(b);
            std::this_thread::sleep_for(1s);
        }
    };
    std::thread t2(RUN_C,c,std::ref(b));
    t1.join();
    t2.join();
    return 0;
}

因为友元函数没有this指针,则参数要有三种情况:

要访问非static成员时,需要对象做参数
要访问static成员或全局变量时,则不需要对象做参数
如果做参数的对象是全局对象,则不需要对象做参数
友元函数的位置
因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且没有区别。

友元函数的调用
直接调用,不需要通过对象或指针

友元类个人认为主要在结合Pimp使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值