循环引用的问题

时间:2013-10-21 09:25:19

标签: c++

假设我们有一个名为TestAPI的类和一个名为UserAPI的类。创建类UserAPI的对象并将其包含在类TestAPI的标题中。

现在,对象UserAPI的实例必须能够访问TestAPI实例的私有成员变量,但这不起作用,因为没有创建特定对象。我希望我的库的用户在他们的代码中创建一个对象(TestAPI),以便稍后创建该对象。

示例:

main.cpp
{
    TestAPI test;
    test.User.SomeExampleToChangeRequest(); 
}

class TestAPI
{
    friend class UserAPI;
    public:
        UserAPI User;

    private:
        HINTERNET _hRequest;    // Variable which needs to be accessed from User    
};

现在是一个来自UserAPI类的方法来更改请求句柄

UserAPI::SomeExampleToChangeRequest ()
{
    // how do I access _hRequest now? 
    // TestAPI._hRequest will not work since it's not static and class "global"
}

我该如何表演?将此定义为朋友仅适用于访问权限,并不能解决我的问题。

3 个答案:

答案 0 :(得分:1)

使用C ++理解面向对象设计有两个主要的改进领域。

  • 您提供私人会员访问权的首选应该是公开方法,而不是friend
  • 要在方法中访问其他类型的对象,您应该传递该类型的对象。不要开始考虑静态或全局对象,除非这是你真正想要的。

我在下面发布了一些代码段。把它们放在一起解决你的问题。

class TestAPI {
public:
    // method to modify _hRequest
    void set_hRequest(HINTERNET& in_hRequest) {
        _hRequest = in_hRequest;
    }

    // method to access _hRequest
    HINTERNET& get_hRequest() {
        return _hRequest;
    }

private:
    HINTERNET _hRequest;
};

UserAPI::SomeExampleToChangeRequest(TestAPI& t) {
    // use 't' to access TestAPI here, like so ...
    HINTERNET h = t.get_hRequest();  
}

用户创建TestAPI对象后,让他们通过引用UserAPI::SomeExampleToChangeRequest()方法传递它。另外,使用gbjbaanb提到的前向声明来帮助编译器。

答案 1 :(得分:0)

我认为更清楚地解释为什么开箱即用的原因是UserAPI的每个实例都不知道它的创建位置或用途。

老实说,这里有这样的直接链接,你可能需要在构造它时允许它调用_hRequest方法时为UserAPI提供某种“父”TestAPI指针/引用。

编辑:

基本上将UserAPI的定义更改为以下内容:

// Forward declaration
class TestAPI;

class UserAPI
{
public:

    UserAPI( TestAPI* inParent )
    : m_parent ( inParent )
    {}

private:

    // Let's make this private to force construction with a TestAPI parent
    UserAPI(){}

    TestAPI* m_parent;
};

注意前向声明,因为编译器需要知道它存在。 如果您正在使用头文件,那么将此声明放在userAPI.h的顶部,并且只在userAPI.cpp中包含testAPI.h。

请记住,这不允许您从userAPI.h中调用任何TestAPI函数,但它将在userAPI.cpp中提供完全访问权限

因此需要在userAPI.cpp中定义UserAPI::SomeExampleToChangeRequest

UserAPI::SomeExampleToChangeRequest ()
{
    // The TestAPI variable or function can now be accessed like so
    m_parent->_hRequest;
}

快速说明:如果您不想使用单独的header和cpp文件,那么只要您在TestAPI定义之后定义UserAPI::SomeExampleToChangeRequest,那么您就可以开始了。

最后注意:正如Happy所说,朋友并不是真的需要,应该在面向对象的C ++中谨慎使用。最好使用公共函数来访问该参数

答案 2 :(得分:0)

您可以创建一个forward declaration,这是一种说“将在稍后提供此定义”的方式,因此您的代码将正确检查语法,并且编译器将在以后为您排序(它知道两个类的完整定义。)

然而,存在局限性。因为编译器对前向声明的类一无所知,所以不能引用它的方法或它的大小。这意味着你几乎必须通过指针来引用它,你希望它能用智能指针包裹。