【问题标题】:c++ forward declaration + ifndef also needs pointers [closed]c ++前向声明+ ifndef也需要指针[关闭]
【发布时间】:2020-09-01 19:32:13
【问题描述】:

数组:

#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;
}

【问题讨论】:

  • 重要阅读:Why should I not #include <bits/stdc++.h>?Why is “using namespace std;” considered bad practice?。尤其是当 在标头中一起使用时,这是一种很好的方法,可以创建非常讨厌的错误并将编译时间增加一个数量级。
  • 再一次证明#include &lt;bits/stdc++.h&gt;using namespace std; 即使在所谓的“竞争性编程”中也是不可接受的。人们从一开始就养成坏习惯,然后坚持下去。
  • 你到底在问什么?我无法跟随你的思路。您尝试了指针,但没有成功,您不知道是否应该坚持使用 C ......但这与您粘贴在这里的代码有什么关系?您需要帮助的实际问题是什么?
  • @MaifeeUIAsad "当使用指针时,我遇到了很多问题,例如,我的地图中只有一个键值对,但在下一行中,大小变成了一个非常大的数字,超出无处。” - 那么您在显示的代码之外做错了其他事情。但我们看不到那是什么。请提供minimal reproducible example。您可能正在访问一个无效的指针。
  • @remy 刚刚添加了两个构造函数,其中 map 作为参数,object 作为参数......并且代码在 main 函数中。

标签: c++ forward-declaration ifndef


【解决方案1】:

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

class Object 有一个 map&lt;string, Value&gt; 成员,class Array 有一个 vector&lt;Value&gt; 成员。这意味着Value 在编译ObjectArray 时必须是完全定义的完整类型,因为mapvector 需要知道它们元素类型的总大小。如果Value 有非指针ArrayObject 成员,则ObjectArray 需要Value 才能成为完整类型,但Value 需要Object 和@987654341 @ 是完整的类型。第 22 条军规!

因此,您必须对 Value 成员使用前向声明和指针/引用,以使这种循环引用正常工作,因为允许对不完整类型的指针/引用。


更新:在采用Object* 参数的Value 构造函数中,您将_object 成员设置为指向超出范围的本地Object 实例并且是当构造函数退出时被销毁,从而使_object 悬空。这就是为什么main() 中的后续val._object-&gt;_members.size() 表达式会产生垃圾(幸运的是代码没有直接崩溃)-val._object 指向无效内存,因此它的members 不是有效的map 对象所以阅读它的size()未定义的行为。这可以追溯到我发布的原始评论:

您可能正在访问一个无效的指针。

要解决这个问题,根据您的实际设计目标,Value 构造函数需要:

  • 动态构造一个新的Object,以后必须是delete。您还必须提供适当的复制构造函数和复制赋值运算符:
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;
}

【讨论】:

  • 有什么办法可以在所有标题中定义这些对象的形状...我只是想避免指针...
  • "我只想避免使用指针" - 为什么?如果您不习惯使用指针,那么您根本不应该使用 C++。指针是 C++ 语言的核心和重要组成部分。
  • pastebin.com/ykH20JDs。在第一行它说我给它的大小,在下一行它只是一个随机数......地图充满了垃圾值......
  • @MaifeeUlAsad 请不要在其他网站上发布代码,edit your question 而是将相关代码放在那里。 SO问题是独立的,外部链接会随着时间的推移而中断。在任何情况下,Object object=Object(members)Value val=Value(&amp;object) 都不会编译,因为 ObjectValue 在您目前显示的代码中没有这样的构造函数。
  • @MaifeeUlAsad 如果您没有正确关注Rule of 3/5/0,就会发生坏事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 1970-01-01
  • 2015-05-02
  • 2011-06-20
相关资源
最近更新 更多