友元的互相依赖问题

       友元,是一种对非成员函数或类提供私有成员访问权限的机制。以关键字friend声明,通常出现在类的起始或结尾处。但是实际使用中也容易碰到友元声明与定义之间的互相依赖问题。

        例子如下,我们对Mutex和Condition Veriable进行封装,由于条件变量的等待函数需要操作原始pthread_mutex_t对象,因此我们需要将条件变量的类声明为Mutex类的友元。我们先封装Mutex。这里包含了我们自己封装的条件变量头文件cond.h,并声明为其友元。

#ifndef __MUTEX_H__
#define __MUTEX_H__

#include <pthread.h>
#include "cond.h"

namespace Pthread
{
class IUncopyable
{
	public:
		IUncopyable(){};
	private:
		IUncopyable(IUncopyable &);
		IUncopyable & operator=(const IUncopyable&);
};
class IMutex
{
	public:
		virtual ~IMutex(){};
		virtual int lock() = 0;
		virtual int trylock() = 0;
		virtual int unlock() = 0;
};
class CMutex: public IMutex, private IUncopyable
{
	friend class CCond;
	public:
		CMutex();
	    ~CMutex();
		int lock();
		int trylock();
		int unlock();
	private:
		pthread_mutex_t m_mutex;
};
class CGuard
{
	public:
		CGuard(IMutex *mutex): m_mutex(mutex){m_mutex->lock();};
		~CGuard(){m_mutex->unlock();};
	private:
		IMutex *m_mutex;
};
}
#endif
#ifndef __MUTEX_H__
#define __MUTEX_H__

#include <pthread.h>
#include "cond.h"

namespace Pthread
{
class IUncopyable
{
	public:
		IUncopyable(){};
	private:
		IUncopyable(IUncopyable &);
		IUncopyable & operator=(const IUncopyable&);
};
class IMutex
{
	public:
		virtual ~IMutex(){};
		virtual int lock() = 0;
		virtual int trylock() = 0;
		virtual int unlock() = 0;
};
class CMutex: public IMutex, private IUncopyable
{
	friend class CCond;
	public:
		CMutex();
	    ~CMutex();
		int lock();
		int trylock();
		int unlock();
	private:
		pthread_mutex_t m_mutex;
};
class CGuard
{
	public:
		CGuard(IMutex *mutex): m_mutex(mutex){m_mutex->lock();};
		~CGuard(){m_mutex->unlock();};
	private:
		IMutex *m_mutex;
};
}
#endif

   接下来我们对条件变量封装,由于先前在CMutex类中声明了CCond为友元,因此这里可以对其private成员操作。

#ifndef __COND_H__
#define __COND_H__

#include <pthread.h>
#include "mutex.h"

namespace Pthread
{
class ICond
{
	public:
		virtual ~ICond(){};
		virtual int wait(CMutex &) = 0;
		virtual int signal() = 0;
		virtual int broadcast() = 0;
};
class CCond: public ICond
{
	public:
		CCond();
		~CCond();
		int wait(CMutex &);
		int signal();
		int broadcast();
	private:
		pthread_cond_t m_cond;
};
}
#endif
#include "cond.h"

namespace Pthread
{
CCond::CCond()
{
	pthread_cond_init(&m_cond, NULL);
}
CCond::~CCond()
{
	pthread_cond_destroy(&m_cond);
}
int CCond::wait(CMutex &mutex)
{
	return pthread_cond_wait(&m_cond, &mutex.m_mutex);
}
int CCond::signal()
{
	return pthread_cond_signal(&m_cond);
}
int CCond::broadcast()
{
	return pthread_cond_broadcast(&m_cond);
}
}


    接下来是编译,但是编译却出错了,那是由于mutex.h与cond.h互相依赖了,那么怎么解开呢?我们知道当对象定义为指针或引用时,编译器是确定了它的占用空间的,即sizeof(void *)。比如说CMutex *mutex,编译器并不需要知道CMutex类的占用空间。所以我们在int CCond::wait(CMutex &mutex)使用了CMutex的引用。那么可以将cond.h的#include "mutex.h"放入cond.cpp中,再于cond.h中声明一句class CMutex, 告诉编译CMutex是个类即可。


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值