循环引用的问题
Problems with circular reference
假设我们有一个名为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"
}
我该如何执行此操作?将其定义为朋友仅适用于访问权限,并不能解决我的问题。
在理解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 提到的前向声明来帮助编译器。
为什么这不可能开箱即用的更清晰的方法是,UserAPI 的每个实例都不知道它是在哪里创建的或它的用途。
老实说,在这里使用这种直接链接,您可能需要在构造UserAPI以允许其调用_hRequest方法时为其提供某种"父"TestAPI指针/引用。
编辑:
基本上将用户API的定义更改为以下内容:
// 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中定义UserAPI::SomeExampleToChangeRequest
.cpp
UserAPI::SomeExampleToChangeRequest ()
{
// The TestAPI variable or function can now be accessed like so
m_parent->_hRequest;
}
最后一点:如果您不想使用单独的头文件和 cpp 文件,那么只要您在定义 TestAPI 之后定义UserAPI::SomeExampleToChangeRequest
那么您就可以开始了。
最后说明:正如 Happy 所提到的,朋友并不是真正需要的,应该在面向对象C++中谨慎使用。最好创建一个公共函数来访问该参数
您可以创建一个前向声明,这是一种表示"稍后将提供此定义"的方法,以便您的代码将正确检查语法,编译器稍后将为您整理内容(它知道这两个类的完整定义)。
但是,存在局限性。由于编译器对前向声明的类一无所知,因此无法引用其方法或大小。这意味着您几乎必须通过指针来引用它,您希望将其包装在智能指针中。
- 使用运算符 [] 引用 std::vector 上最后一个元素时出现问题<>
- Xcode 语义问题引用或以前定义的代码
- C++ 关于指针取消引用的技术问题
- 移动赋值运算符;尝试引用已删除的函数.我该如何解决这个问题?
- 棘手的按值传递和按引用递归问题传递
- 当我尝试通过 arduino 上的引用传递布尔数组时出现问题
- 编译问题:在函数"_start"中:未定义对"主"的引用 collect2:错误:ld 返回 1 个退出状态
- 取消引用向量时出现问题
- 有关从C++中的不同源文件引用类的问题
- C++:取消引用十六进制值,有点语法问题
- 运行veins_inet示例 - 未定义的引用的 Omnet++ 问题
- C++ - 对 PCM::getInstance() 的未定义引用问题
- 通过键入的引用问题传递函数
- 一个关于继承和引用的C++问题
- 关于引用数组位置的问题
- printf(时差程序)中的引用问题
- 无法取消引用超出范围的向量迭代器 - 有什么问题?
- "Field has incomplete type"引用自己的类的问题
- 指针范围问题和返回类中封装的指针向量内的指针引用
- 使用 opencv 和 C++ - 未定义的引用的链接器出现问题