2016-10-09 31 views
-2

在我有一个与另一个类进行通信的类(如API)并从该类获得回调的情况下,处理循环包含的最佳方式是什么。当需要传回值时避免循环包含

假设我有一个类

.H

class Requestor; 

class Api 
{ 
public: 
    Api(); 
    void Request(); 
    int DoStuff(); 

private: 
    Requestor *p_rq_; 

}; 

的.cpp

#include "api.h" 
#include "requestor.h" 


Api::Api() 
{ 

} 


void Api::Request() { 

    this->DoStuff(); 

} 


void Api::ReturnRequestId(int id) { 

    this->p_rq->SetLastRequestId(id); 

} 

.H

class Api; 

class Requestor 
{ 
public: 
    Requestor(); 
    void MakeRequest(); 
    void SetLastRequestId(int); 

private: 
    Api api_; 
    int last_request_id_; 

}; 

的.cpp

#include "requestor.h" 
#include "api.h" 

Requestor::Requestor() 
{ 

} 


void Requestor::MakeRequest() { 

    this->api_.Request(); 

} 

void Requestor::SetLastRequestId(int id) { 

    this->last_request_id_ = id; 

} 

如果请求者发送一个请求,并在某些时候API获取的ID,并希望传递回请求者,我怎么能做到这一点,而不包括每个人的.h文件中这将导致循环包容? 假设我不能简单地使用MakeRequest函数返回id,因为我不想持有该线程,直到api获取id为止?

我对C++和编程相当陌生,所以我可能会错过显而易见的解决方案。因为我需要调用对方的成员函数,所以我的理解是前向声明在这里不起作用。

另外,Api和Requestor应该是独立的库,所以我不能让它们成为一个类。

+0

你有没有尝试在'Requestor.h'中包含'Api.h'?您需要定义成员非指针的定义。将不会有通告。 – LogicStuff

+0

而不是一个实例,你可以在请求者中有一个指向Api的指针,在构造函数中创建它并在析构函数中删除它。或者,如果您想进行大量输入,请使用auto_ptr。 – cup

+0

@cup'auto_ptr'已弃用,不应再使用。相反,应该使用'shared_ptr','unique_ptr'和'weak_ptr'。 –

回答

1

你有两个不同的问题,你的类并多次包含同一头文件之间的循环依赖。

多重包含不仅仅是由简单的循环依赖造成的,就像你的情况一样。确保一个头文件的常用方法是在源文件中一次且只有一次使用include guard。通常,一个头文件是这样的:

#ifndef SOME_UNIQUE_NAME_ 
#define SOME_UNIQUE_NAME_ 

... header contents ... 

#endif 

这确保了无论是头被多少次,包括在源文件中(直接或间接),只有第一次的内容实际上包括在内,后续的夹杂物由于该宏而被预处理器跳过。宏名称必须是唯一的(出于显而易见的原因),并且它通常是某种前缀,接着是标题名称,例如LIBNAME_MODULENAME_REQUESTOR_H_

一种广泛使用的替代方案,通过最先进的编译器的支持,即使没有标准,据我所知,是在头的开始使用pragma指令:

#pragma once 

... header contents 

你的另一个问题是循环依赖在你的班级之间。在这里你已经找到了一种解决方法:你的Api类拥有一个指向Requestor对象的指针,而不是对象本身。这允许您在Api.h中使用前向声明,而不包括完整的类定义。 然而,Requestor类拥有一个Api对象,而不仅仅是一个指针,所以完全Api类定义必须在声明api_成员的位置可用。所以在这种情况下,你不能使用Api类的前向声明,你必须实际包含完整的定义。

+1

您不应该在大写字母前加一个'_'。我建议不要使用'__'。标准库对其库使用这种约定,如果使用相同的约定,则可以混淆代码。查看更多细节[在C中包括守护约定](http://stackoverflow.com/questions/17307540)(虽然这是关于c它与C++是一样的),你最好选择在谷歌风格指南中提到的那个[Naming Include Guards]的答案(http://stackoverflow.com/a/4867672/1960455)。 –

+0

正确,固定,愚蠢的错误。谢谢。 – Ionut

1

使用

#ifndef __filex__ 
#define __filex__ 

在每个.H开始和

#endif 

末。

这样,.h文件是只读一次