首页 > 解决方案 > 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;
}

标签: c++forward-declarationifndef

解决方案


在这种情况下,您无法避免前向声明和指针。

class Objectmap<string, Value>会员,class Array也有vector<Value>会员。这意味着Value必须是一个完全定义的、完整的类型,Object并且Array正在被编译,因为map并且vector需要知道它们元素类型的总大小。如果Value要具有非指针ArrayObject成员,则ObjectandArray需要Value是完整类型,但Value需要ObjectandArray是完整类型。第 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;
}

推荐阅读