C++ C+中嵌套类型/类的前向声明+;
我最近陷入了这样的境地:C++ C+中嵌套类型/类的前向声明+;,c++,class,nested,forward-declaration,C++,Class,Nested,Forward Declaration,我最近陷入了这样的境地: class A { public: typedef struct/class {…} B; … C::D *someField; } class C { public: typedef struct/class {…} D; … A::B *someField; } 通常可以声明类名: class A; 但是不能向前声明嵌套类型,以下原因会导致编译错误 class C::D; 有什么想法吗?< P > >你不能这么做,这是C++语
class A
{
public:
typedef struct/class {…} B;
…
C::D *someField;
}
class C
{
public:
typedef struct/class {…} D;
…
A::B *someField;
}
通常可以声明类名:
class A;
但是不能向前声明嵌套类型,以下原因会导致编译错误
class C::D;
有什么想法吗?< P > >你不能这么做,这是C++语言中的一个漏洞。您必须取消嵌套至少一个嵌套类。我不认为这是一个答案,但这是一个有趣的发现: 如果在名为C的命名空间中重复结构声明,则一切正常(至少在gcc中)。 当找到C的类定义时,它似乎会悄悄地覆盖NAMC空间
namespace C {
typedef struct {} D;
}
class A
{
public:
typedef struct/class {...} B;
...
C::D *someField;
}
class C
{
public:
typedef struct/class {...} D;
...
A::B *someField;
}
我需要一个前瞻性的参考,比如:
class IDontControl::Nested; // But this doesn't work.
我的解决办法是:
class IDontControl_Nested; // Forward reference to distinct name.
后来我可以使用完整的定义:
#include <idontcontrol.h>
// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
// Needed to make a forwarding constructor here
IDontControl_Nested(int i) : Nested(i) { }
};
#包括
//我这样定义向前参考:
类IDontControl\u嵌套:公共IDontControl::嵌套
{
//需要在此创建转发构造函数
IDontControl_嵌套(inti):嵌套(i){
};
如果存在复杂的构造函数或其他无法顺利继承的特殊成员函数,则此技术可能会遇到更多麻烦。我可以想象某些模板魔法的反应会很糟糕
但在我非常简单的例子中,它似乎是有效的。如果你真的想避免在头文件中包含讨厌的头文件,你可以这样做: hpp文件:
class-MyClass
{
公众:
模板
void doesStuff();
};
cpp文件
#包括“MyClass.hpp”
#包括“第三方.hpp”
模板void MyClass::doesStuff()
{
// ...
}
但是:
因此,是的,权衡…这将是一个解决办法(至少对于问题中描述的问题——而不是实际问题,即当无法控制
C
的定义时):
这可以通过将外部类声明为命名空间来实现 示例:我们必须使用嵌套类others::a::嵌套在others_a.h中,这是我们无法控制的 其他
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
名称空间其他{
结构A{
嵌套结构{
嵌套(inti):i(i){}
int i{};
void print()const{std::cout如果您有权更改类C和D的源代码,则可以分别取出类D,并在类C中输入它的同义词:
class CD {
};
class C {
public:
using D = CD;
};
class CD;
为什么需要它?请注意,如果它是被定义的同一个类的成员,则可以向前声明:类X{class Y;Y*a;};类X::Y{};这个解决方案对我有效(命名空间C{class D;};):我找到了一个解决方案,我在cygwin gcc中尝试了这个方法,但如果您尝试在类a定义中引用a.someField.C::D,它就不会编译。它实际上引用了命名空间中的(空)结构,而不是类C中的结构(顺便说一句,它不会在MSVC中编译)。它给出了错误:“'class C'重新声明为不同类型的符号”看起来像是一个GCC错误。它似乎认为名称空间名称可以在同一范围内隐藏类名。谢谢你的回答。在我的情况下,它们不是我的嵌套类。我希望通过一点向前引用来避免一个巨大的库头文件依赖。我想知道C++11是否修复了它?哦。这正是我不想让google出现的。无论如何,谢谢你的帮助他回答得很简洁。同样的,这里有人知道为什么不可能吗?似乎有有效的用例,这种缺乏可以在某些情况下阻止体系结构的一致性。你可以使用朋友,并且只需评论一下,你就可以用它来处理C++中的漏洞。在C++11中,你可以通过在派生类中使用basename::basename;
来继承构造函数,这样复杂的构造函数就没有问题了。这是一个很好的技巧,但如果在同一个头中使用指向IDontControl::Nested的指针(它在头中向前声明),它将不起作用并从外部代码访问,该代码还包括IDontControl的完整定义。(因为编译器将不匹配IDontControl_Nested和IDontControl::Nested)解决方法是执行静态的CAST。我建议做相反的操作,让类在外面,在类中使用<代码> Type Fux/Cuth>,Heck是一个代码> HPP< /Cord>文件LOL,一个.HPP头文件用于C++项目,以区别于C文件头文件,通常在.SA中使用C++和C。ME项目有些人喜欢C++文件的HPP和.CPP,明确地处理它们处理的文件类型,以及C文件的.H和.C。它可能是有效的,但它是无文件的。它的工作原理是:<代码>:::B/<代码>以相同的方式被破坏,不管<代码> < /COD>是类或命名空间。它不能用CLAN或GCC工作。发现外部类被声明为与命名空间不同的东西。
class C_base {
public:
class D { }; // definition of C::D
// can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
class B { };
C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
// Danger: Do not redeclare class D here!!
// Depending on your compiler flags, you may not even get a warning
// class D { };
A::B *someField;
};
int main() {
A a;
C::D * test = a.someField; // here it can be called C::D
}
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif
class MyClass {
public:
MyClass(int i);
~MyClass();
void print() const;
private:
std::unique_ptr<others::A::Nested> _aNested;
};
#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"
MyClass::MyClass(int i) :
_aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
_aNested->print();
}
class CD {
};
class C {
public:
using D = CD;
};
class CD;