c++ - c++前向声明+ifndef也需要指针
问题描述
大批:
#ifndef ARRAY_H
#define ARRAY_H
#include <bits/stdc++.h>
using namespace std;
namespace Maifee{
class Value;
class Array {
public:
Array();
vector<Value> _elements;
};
}
#endif // ARRAY_H
目的 :
#ifndef OBJECT_H
#define OBJECT_H
#include <bits/stdc++.h>
#include "value.h"
using namespace std;
namespace Maifee{
class Value;
class Object{
public:
Object();
map<string, Value> _members;
};
}
#endif // OBJECT_H
价值 :
#ifndef VALUE_H
#define VALUE_H
#include <bits/stdc++.h>
#include "array.h"
#include "object.h"
using namespace std;
namespace Maifee{
class Array;
class Object;
class Value {
public:
Value();
Value(Object *__object);
Array *_array;
Object *_object;
};
}
#endif // VALUE_H
我正在尽我最大的努力学习 C++。凭借我对 C++ 的一点点了解,我正在尝试编写一些代码。我移动 C++ 的第一个原因,指针需要很多时间。
在这里,我正在编写这些代码,其中需要前向声明,因此即使在使用前向声明和 ifndef 之后,我也需要使用指针,我真的不想要。
谁能真正帮我解决这个问题,我怎样才能消除循环依赖?
我需要回到C吗?
使用指针时,我遇到了很多问题,例如,我的地图中只有一个键值对,但在下一行,大小变成了一个非常大的数字,不知从何而来。
main 里面的代码:
Object object=Object();
cout << "pop obj tem len" << object._members.size() << endl; //gives 0 as expected
object._members = members;
cout << "pop obj tem len" << object._members.size() << endl; //gives the expected number
Value val=Value(&object);
cout << val._object->_members.size() << "size here" << endl; //gives a random number
带有 Object 参数的 Value 的构造函数:
Value::Value(Object *__object)
{
Object object;
object._members.insert(__object->_members.begin(), __object->_members.end());
_object = &object;
}
解决方案
在这种情况下,您无法避免前向声明和指针。
class Object
有map<string, Value>
会员,class Array
也有vector<Value>
会员。这意味着Value
必须是一个完全定义的、完整的类型,Object
并且Array
正在被编译,因为map
并且vector
需要知道它们元素类型的总大小。如果Value
要具有非指针Array
和Object
成员,则Object
andArray
需要Value
是完整类型,但Value
需要Object
andArray
是完整类型。第 22 条军规!
因此,您必须对Value
成员使用前向声明和指针/引用,以使这种循环引用正常工作,因为允许对不完整类型的指针/引用。
更新:在Value
带有参数的构造函数中Object*
,您将_object
成员设置为指向Object
超出范围并在构造函数退出时被销毁的本地实例,从而留下_object
悬空。这就是为什么后面的val._object->_members.size()
表达式main()
会产生垃圾(你很幸运,代码没有直接崩溃)——val._object
指向无效的内存,所以它members
不是一个有效的map
对象,所以读取它size()
是未定义的行为。这可以追溯到我发布的原始评论:
您可能正在访问一个无效的指针。
为了解决这个问题,根据您的实际设计目标,Value
构造函数需要:
- 动态构造一个新的
Object
,稍后必须delete
'd。您还必须提供适当的复制构造函数和复制赋值运算符:
Value::Value()
{
_object = NULL;
_array = NULL;
}
Value::Value(Object *__object)
{
_object = new Object;
_array = NULL;
if (__object)
_object._members = __object->_members;
}
Value::Value(const Value &__value)
{
_object = new Object;
_array = NULL;
if (__value._object)
_object._members = __value._object->_members;
}
Value::~Value()
{
delete _object;
}
Value& Value::operator=(const Value &__value)
{
if (&__value != this)
{
Value tmp(__value);
std::swap(_object, tmp._object);
std::swap(_array, tmp._array);
}
return *this;
}
- 只需存储
Object*
它给出的指针:
Value::Value(Object *__object)
{
_object = __object;
_array = NULL;
}
推荐阅读
- mongodb - 从两个集合中如何过滤不匹配的数据
- ios - UIImage 裁剪出透明像素
- r - 删除两个字符串之间的字符串
- java - 当feign调用remote方法返回null时,你的项目是如何处理的?
- javascript - 仅在编辑模式下禁用列 Syncfusion GRID
- bootstrap-4 - 主动导航药丸具有与信息按钮相同的颜色
- docker - Cloc 不在 Docker 容器中进行递归搜索
- mysql - 我想知道 Django 查询集中的排名
- php - 为什么在 php 中运行 javascript 警报后我会被重定向到空白页面?
- python - 绘制 kdeplot 的不常见部分