假设我们有一个名为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"
}
我该如何表演?将此定义为朋友仅适用于访问权限,并不能解决我的问题。
答案 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,这是一种说“将在稍后提供此定义”的方式,因此您的代码将正确检查语法,并且编译器将在以后为您排序(它知道两个类的完整定义。)
然而,存在局限性。因为编译器对前向声明的类一无所知,所以不能引用它的方法或它的大小。这意味着你几乎必须通过指针来引用它,你希望它能用智能指针包裹。