温习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使用

你可能感兴趣的:(北漂-Mobvista.,C++,c++)