Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中转发typedef声明+;_C++_Typedef_Forward Declaration - Fatal编程技术网

C++ 在C+中转发typedef声明+;

C++ 在C+中转发typedef声明+;,c++,typedef,forward-declaration,C++,Typedef,Forward Declaration,为什么编译器不允许我向前声明一个typedef 假设这是不可能的,那么保持包含树较小的最佳实践是什么?因为要声明类型,需要知道其大小。您可以正向声明指向该类型的指针,或向类型定义指向该类型的指针 如果您真的愿意,可以使用pimpl习惯用法来减少包含。但是如果你想使用类型,而不是指针,编译器必须知道它的大小 编辑:j_random_hacker为这个答案添加了一个重要的限定条件,基本上,使用类型需要知道大小,但如果我们只需要知道类型存在,就可以进行转发声明,以便创建指向该类型的指针或引用。因为OP

为什么编译器不允许我向前声明一个typedef


假设这是不可能的,那么保持包含树较小的最佳实践是什么?

因为要声明类型,需要知道其大小。您可以正向声明指向该类型的指针,或向类型定义指向该类型的指针

如果您真的愿意,可以使用pimpl习惯用法来减少包含。但是如果你想使用类型,而不是指针,编译器必须知道它的大小


编辑:j_random_hacker为这个答案添加了一个重要的限定条件,基本上,使用类型需要知道大小,但如果我们只需要知道类型存在,就可以进行转发声明,以便创建指向该类型的指针或引用。因为OP没有显示代码,但抱怨它无法编译,所以我假设(可能是正确的)OP正在尝试使用该类型,而不仅仅是引用它

您可以执行正向typedef。但是做

typedef A B;
您必须首先转发声明
A

class A;

typedef A B;

C++中(但不是纯C),只要两个定义完全相同,就可以对Type一个类型进行两次完全合法:

// foo.h
struct A{};
typedef A *PA;

// bar.h
struct A;  // forward declare A
typedef A *PA;
void func(PA x);

// baz.cc
#include "bar.h"
#include "foo.h"
// We've now included the definition for PA twice, but it's ok since they're the same
...
A x;
func(&x);

对于像我这样的人,他们正期待着用TyPulf定义一个C样式结构,在一些C++代码中,我发现了一个如下……/P>的解决方案。

// a.h
 typedef struct _bah {
    int a;
    int b;
 } bah;

// b.h
 struct _bah;
 typedef _bah bah;

 class foo {
   foo(bah * b);
   foo(bah b);
   bah * mBah;
 };

// b.cpp
 #include "b.h"
 #include "a.h"

 foo::foo(bah * b) {
   mBah = b;
 }

 foo::foo(bah b) {
   mBah = &b;
 }
要“fwd声明一个typedef”,您需要fwd声明一个类或结构,然后您可以声明typedef类型。编译器可以接受多个相同的typedef

长格式:

class MyClass;
typedef MyClass myclass_t;
简表:

typedef class MyClass myclass_t;

只有当您不打算使用类型本身(在此文件的作用域中),而是使用指向它的指针或引用时,才可以使用前向声明而不是完整的
#include
s

要使用类型本身,编译器必须知道它的大小-因此必须看到它的完整声明-因此需要完整的
#include

但是,编译器知道指针或引用的大小,而不考虑指针对象的大小,因此前向声明就足够了—它声明了一个类型标识符名称

有趣的是,当使用指向
结构
类型的指针或引用时,编译器可以处理不完整的类型,而无需向前声明指针对象类型:

// header.h

// Look Ma! No forward declarations!
typedef class A* APtr; // class A is an incomplete type - no fwd. decl. anywhere
typedef class A& ARef;

typedef struct B* BPtr; // struct B is an incomplete type - no fwd. decl. anywhere
typedef struct B& BRef;

// Using the name without the class/struct specifier requires fwd. decl. the type itself.    
class C;         // fwd. decl. type
typedef C* CPtr; // no class/struct specifier 
typedef C& CRef; // no class/struct specifier 

struct D;        // fwd. decl. type
typedef D* DPtr; // no class/struct specifier 
typedef D& DRef; // no class/struct specifier 

我也有同样的问题,不想在不同的文件中处理多个typedef,所以我通过继承解决了这个问题:

是:

简单地

ParticleSystem

正如Bill Kotsias所指出的,保持点的typedef细节私有并向前声明它们的唯一合理方法是继承。不过,使用C++11可以做得更好一些。考虑这一点:

// LibraryPublicHeader.h

class Implementation;

class Library
{
...
private:
    Implementation* impl;
};
//LibraryPrivateImplementation.cpp
//令人烦恼的是,这不起作用:
//
//typedef std::共享的ptr实现;
//然而,这确实是,而且几乎是一样好。
类实现:public std::shared\u ptr
{
公众:
//C++11允许我们轻松地复制所有构造函数。
使用shared_ptr::shared_ptr;
};

像@BillKotsias一样,我使用了继承,它对我很有效

我改变了这个混乱(这需要我声明中的所有boost头*.h)

#包括
#包括
#包括
#包括
#包括
#包括
#包括
类型DEF增压::蓄能器::蓄能器组>VANILLA蓄能器组;
std::唯一的ptr acc;
加入本声明(*.h)

class蓄能器;
std::唯一的ptr acc;
实现(*.cpp)是

#包括
#包括
#包括
#包括
#包括
#包括
#包括
类别:公共
增压::蓄能器::蓄能器组>
{
};

我用继承和构造函数继承(?)替换了
typedef
使用

原创的

using CallStack = std::array<StackFrame, MAX_CALLSTACK_DEPTH>;

+1最终,因为虽然您在技术上无法“转发typedef”(即您无法编写“typedef A;”),但您几乎肯定可以使用上述技巧完成OP想要完成的任务。但请注意,如果typedef发生更改,您也可能会更改所有转发声明,如果旧的和新的typedef使用具有相同接口的类型,您可能会错过这一点。一般来说,这不是一个有用的解决方案。例如,如果
typedef
使用前向声明命名一个复杂的多级模板类型,这种方式相当复杂和困难。更不用说它可能需要深入了解隐藏在默认模板参数中的实现细节。最终的解决方案是一个冗长且不可读的代码(特别是当类型来自不同的名称空间时),很容易在原始类型中发生更改。此外,这显示了“实现细节”(即使不完全,但仍然…),而转发声明背后的思想是隐藏它们。@windfinder:它是:模板类a;A型和B型;好的,类类型的前向声明声明这些类型而不知道它们的大小。此外,除了能够定义指向此类不完整类型的指针和引用外,还可以声明(但未定义)函数,这些函数接受参数和/或返回此类类型的值。抱歉,我认为这不是一个好的假设。这个答案离题了。typedef转发声明的情况就是这样。维护编号No。这种事情迟早会在keister中发生。@MarkStorer,至少编译器会捕捉到任何差异并生成错误。我用Visual C++验证了这一点。但是,既然代码“< < /CODE>定义为空”,您如何定义<代码> A<代码>字段?@ LittleJohn,这个解决方案的问题是,虚拟名称名为BAH不被认为是公共API的一部分。请参阅转发的delcare文件。这与投票最多的问题有何不同@JorgeLeitão你看不出有什么不同吗?它没有在一行中显示如何做到这一点。
ParticleSystem
// LibraryPublicHeader.h

class Implementation;

class Library
{
...
private:
    Implementation* impl;
};
// LibraryPrivateImplementation.cpp

// This annoyingly does not work:
//
//     typedef std::shared_ptr<Foo> Implementation;

// However this does, and is almost as good.
class Implementation : public std::shared_ptr<Foo>
{
public:
    // C++11 allows us to easily copy all the constructors.
    using shared_ptr::shared_ptr;
};
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/max.hpp>

typedef boost::accumulators::accumulator_set<float,
 boost::accumulators::features<
  boost::accumulators::tag::median,
  boost::accumulators::tag::mean,
  boost::accumulators::tag::min,
  boost::accumulators::tag::max
 >> VanillaAccumulator_t ;
std::unique_ptr<VanillaAccumulator_t> acc;
class VanillaAccumulator;
std::unique_ptr<VanillaAccumulator> acc;
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/max.hpp>

class VanillaAccumulator : public
  boost::accumulators::accumulator_set<float,
    boost::accumulators::features<
      boost::accumulators::tag::median,
      boost::accumulators::tag::mean,
      boost::accumulators::tag::min,
      boost::accumulators::tag::max
>>
{
};
using CallStack = std::array<StackFrame, MAX_CALLSTACK_DEPTH>;
struct CallStack // Not a typedef to allow forward declaration.
  : public std::array<StackFrame, MAX_CALLSTACK_DEPTH>
{
  typedef std::array<StackFrame, MAX_CALLSTACK_DEPTH> Base;
  using Base::Base;
};
class CallStack;