C++学习 十四、类的进阶(1)友元

C++学习 十四、类的进阶(1)友元

前言

本篇开始类的进阶内容,友元。

友元

类的访问控制权限要求,对于类的私有部分,只有类的公有方法才能访问。

友元是一个例外。

关键字friend表示友元声明。

友元函数

友元函数不属于该类成员,但可以访问该类的私有成员。友元函数可以是普通函数,也可以是其它类的成员函数。

类的友元函数声明必须放在类中,示例如下:

#include <cstdio>
#include <iostream>
class SimpleClass{
	private:
		int a_;
	public:
        enum myEnum {ONE=1, TWO, THREE};
        const int b = 10; 
        myEnum c;
        
		SimpleClass(int a=1);
		void set(int);
		int get();
		
		void add(int x) { // inline method
			a_ += x;
		}

        friend int geta(const SimpleClass);
		
};

int geta(const SimpleClass c){
    return c.a_;
}

SimpleClass::SimpleClass(int a){
	a_ = a;
}

int main()
{
 	SimpleClass sc; 
    std::cout << geta(sc);

  	return 1;
}

SimpleClass类的友元函数int geta(const SimpleClass)可以访问类的私有成员a_

注意:友元函数必须在类中使用friend关键字声明,但在定义时不能使用friend关键字,除非在类内同时声明并定义。(在类声明中定义的友元函数也将成为内联函数)。

注意:友元函数可以声明在privatepublicprotected中,位置无关紧要。

友元类

可以把类B声明为类A的友元类,这样类B中的所有成员函数都能访问类A中的私有成员。

类的友元类声明也必须放在类中,示例如下:

#include <cstdio>
#include <iostream>

class SimpleClass{
	private:
		int a_;
	public:
        enum myEnum {ONE=1, TWO, THREE};
        const int b = 10; 
        myEnum c;
        
		SimpleClass(int a=1);
		void set(int);
		int get();
		
		void add(int x) { // inline method
			a_ += x;
		}

        friend int geta(const SimpleClass);
        friend class fClass;
		
};

class fClass{
    public:
        int geta(const SimpleClass);
};

int geta(const SimpleClass c){
    return c.a_;
}

int fClass::geta(const SimpleClass c){
    return c.a_;
}

SimpleClass::SimpleClass(int a){
	a_ = a;
  	//b = a;
}

int main()
{
 	SimpleClass sc; 
    fClass fc;
    std::cout << geta(sc) << std::endl;
    std::cout << fc.getb(sc) << std::endl;

  	return 1;
}

SimpleClass类的友元类fClass中的成员函数fClass::geta()也能够访问SimpleClass的私有成员a_

注意friend class fClass同时声明了类fClass的存在,以及fClassSimpleClass的友元类,也就是说同时进行了类前置声明与友元声明。与下面的先前置声明类,后友元声明的方法等效:

class B;

Class A{
	private:
		// data member
	public:
		friend B;
}

class B{
	private:
		// data member
	public:
		// function member
};

友元成员函数

如果只需要类B的某个成员函数访问类A的私有成员,则可以将该成员函数声明为类A的友元成员函数。

注意:只有公有方法,才能成为友元成员函数。

友元成员函数的定义比较麻烦,需要特别关注类声明的顺序。示例如下:

class SimpleClass{
	private:
		int a_;
	public:
        enum myEnum {ONE=1, TWO, THREE};
        const int b = 10; 
        myEnum c;
        
		SimpleClass(int a=1);
		void set(int);
		int get();
		
		void add(int x) { // inline method
			a_ += x;
		}

        friend int geta(const SimpleClass);
        friend class fClass;
        friend int AClass::geta(const SimpleClass);
};

friend int AClass::geta(const SimpleClass)声明类AClass中的geta()是友元成员函数,因此需要在SimpleClass声明之前,声明AClass

class AClass{
    public:
    int geta(const SimpleClass);
};

class SimpleClass{
	private:
		int a_;
	public:
        enum myEnum {ONE=1, TWO, THREE};
        const int b = 10; 
        myEnum c;
        
		SimpleClass(int a=1);
		void set(int);
		int get();
		
		void add(int x) { // inline method
			a_ += x;
		}

        friend int geta(const SimpleClass);
        friend class fClass;
        friend int AClass::geta(const SimpleClass);
};

AClass声明中,int geta(const SimpleClass)函数使用了SimpleClass类,因此需要在AClass声明之前,声明SimpleClass

class SimpleClass;

class AClass{
    public:
    int geta(const SimpleClass);
};

class SimpleClass{
	private:
		int a_;
	public:
        enum myEnum {ONE=1, TWO, THREE};
        const int b = 10; 
        myEnum c;
        
		SimpleClass(int a=1);
		void set(int);
		int get();
		
		void add(int x) { // inline method
			a_ += x;
		}

        friend int geta(const SimpleClass);
        friend class fClass;
        friend int AClass::geta(const SimpleClass);
};

class SimpleClass;这样的声明称为前置声明,此时编译器知道了SimpleClass是一个类,但不知道SimpleClass类的内部成员。因此,要在SimpleClass类声明后,再定义友元成员函数:

#include <cstdio>
#include <iostream>

class SimpleClass;

class AClass{
    public:
    int geta(const SimpleClass);
};

class SimpleClass{
	private:
		int a_;
	public:
        enum myEnum {ONE=1, TWO, THREE};
        const int b = 10; 
        myEnum c;
        
		SimpleClass(int a=1);
		void set(int);
		int get();
		
		void add(int x) { // inline method
			a_ += x;
		}

        friend int geta(const SimpleClass);
        friend class fClass;
        friend int AClass::geta(const SimpleClass);
};

class fClass{
    public:
        int geta(const SimpleClass);
};

int AClass::geta(const SimpleClass c){
    return c.a_;
}

int geta(const SimpleClass c){
    return c.a_;
}

int fClass::geta(const SimpleClass c){
    return c.a_;
}

SimpleClass::SimpleClass(int a){
	a_ = a;
}

int main()
{
 	SimpleClass sc; 
    fClass fc;
    AClass ac;
    std::cout << geta(sc) << std::endl;
    std::cout << fc.geta(sc) << std::endl;
    std::cout << ac.geta(sc) << std::endl;

  	return 1;
}

如果在SimpleClass前置声明后,类声明前定义友元函数,就会报error: 'c' has incomplete type,也就是SimpleClass类型无法构造完整的对象。

注意:前置声明不能创建对象,不过可以创建对象的指针:

class AAA;
void main(){
	AAA *aaa;
}

后记

本篇内容是类的进阶之,友元。下一篇将继续讲运算符重载。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值