【问题标题】:Friend classes across different namespaces not working and namespace is not recognized跨不同名称空间的朋友类不起作用并且名称空间无法识别
【发布时间】:2021-05-17 05:13:36
【问题描述】:

我在使用 C++ 中的朋友类时遇到问题 我正在向前声明朋友类并使用适当的名称空间,所以我不知道发生了什么。 内部类 MeshNamespace::MeshReferenceElementNamespace::ReferenceElement 的成员仍然无法访问前者的私有成员。除了ReferenceElement.hppMeshNamespace标识符不识别。

如果我在没有命名空间的情况下将其前向声明为class Mesh;,它不会抱怨,但仍然无法正常工作,就像根本没有前向声明一样;

//文件ReferenceElement.hpp

namespace ReferenceElementNamespace {
    class MeshNamespace::Mesh; // ReferenceElement.hpp:27:9: error: use of undeclared identifier 'MeshNamespace'
    class ReferenceElement : public IReferenceElement 
  {
  private:
  vector<Polygon> _referenceElementPolygons;   //(**)
  friend class MeshNameSpace::Mesh; //ReferenceElement.hpp:45:20: error: use of undeclared identifier 'MeshNameSpace'
  };
}

//文件Mesh.hpp

#include "Mesh.hpp"
    using namespace ReferenceElementNamespace;
    namespace MeshNamespace {
          class Mesh : public IMesh{
                  someFunction(ReferenceElement& referenceElement)
                  {
                    ReferenceElement ref;
                    Polygon &polygon = ref._referenceElementPolygons[0];  //Mesh.cpp:216:32: error: '_referenceElementPolygons' is a private member of 'ReferenceElementNamespace::ReferenceElement'
    ReferenceElement.hpp:34:23: note: declared private here   // in line (**)
                  }
         };
    }

编辑:顺便说一句,我意识到前向声明 class Mesh; 而不是 class MeshNamespace::Mesh; 被接受,因为它喜欢在命名空间 ReferenceElementNamespace 中声明一个新类,但后来我在另一个我使用的文件中变得模棱两可MeshNamespaceReferenceElementNamespaceusing。但这并不能解决任何问题

【问题讨论】:

  • 您是否尝试过在命名空间中进行前向声明?例如。 namespace MeshNamespace { class Mesh; } 我已经习惯了不支持嵌套类的前向声明这一事实。您可能指的是命名空间中的一个类,但我不确定编译器是否也这样认为。
  • 顺便说一句。你混合了MeshNamespaceMeshNameSpace
  • 使用namespace MeshNamespace { class Mesh; },我得到了编译:Demo on coliru
  • @Scheff 成功了!非常感谢。我在ReferenceElement.hpp 中的namespace ReferenceElementNamespace { 之前添加了namespace MeshNamespace { class Mesh; },这解决了所有问题。如果你想写,我很乐意接受你的回答
  • @Scheff 你的第二条评论是什么意思?

标签: c++ oop friend


【解决方案1】:

我知道的:

  1. 支持(其他)命名空间中的前向声明。
  2. 不支持嵌套类的前向声明。

OP 写道:

class MeshNamespace::Mesh;

class OtherClass {
friend class MeshNamespace::Mesh;
};

namespace MeshNamespace 中转发声明class Mesh

也可以是class MeshNamespace { class Mesh { } },但这是嵌套类的前向声明(不支持)。

我不确定如何区分它,而且编译器似乎也不能。但是,修复很简单:

namespace MeshNamespace {
class Mesh;
}

class OtherClass {
friend class MeshNamespace::Mesh;
};

Demo on coliru


注意:

自 C++17 起,允许嵌套命名空间定义:
namespace X::Y { } 被认为等于 namespace X { namespace Y { } }

这似乎也适用于类定义。所以,添加一个定义

class MeshNamespace::Mesh { };

namespace MeshNamespace 定义一次之后就可以了。 (但是,在至少定义一次 namespace MeshNamespace 之前,这也是一个错误。)

Demo on coliru

【讨论】:

  • 顺便说一下,正如你看到的,这些类中的每一个都继承自一个只有虚函数的接口,以防我只使用了一个虚方法,比如someFunction而不是一个虚类,我应该为 ReferenceElement 类中的朋友方法添加相应的虚拟方法吗?如果不是我担心当我创建IMesh 的对象时,我可能无法使用方法someFunction,因为它访问IReferenceElement 的私有成员是否没有朋友方法的虚拟声明?跨度>
  • @J.C.VegaO 不确定我是否正确解决了您的其他问题...如果我让基类成为另一个类的朋友,而派生类将“继承”这种友谊-我只是做了一个受保护的内联包装函数,以便派生类可以调用它们允许的东西。
  • @J.C.VegaO Demo on coliru 为“继承”的友谊。
  • Mesh继承自IMeshReferenceElement继承自IReferenceElementMesh::someFunctionReferenceElement 中被声明为朋友。如果我创建并反对IReferenceElement virtualObject,我通常可以像使用ReferenceElement. 的对象一样使用它如果我想做virtualObject.someFunction,这将访问`IMesh, but IMesh` 的私有成员尚未声明@ 987654348@ 作为朋友(只有它的派生类 Mesh 已将派生类 ReferenceElement 声明为朋友)所以我不确定这是否可行
  • @J.C.VegaO 好的。我相信这值得另一个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-21
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 2013-04-17
  • 2015-10-05
相关资源
最近更新 更多