首页 文章

在C中转发typedef的声明

提问于
浏览
204

为什么编译器不允许我转发声明一个typedef?

假设这是不可能的,保持包含树小的最佳做法是什么?

9 回答

  • 2

    你可以转发typedef . 但要这样做

    typedef A B;
    

    你必须先转发声明 A

    class A;
    
    typedef A B;
    
  • 6

    对于那些喜欢我的人,谁想要使用typedef声明一个C风格的结构,在某些c代码中,我找到了一个解决方案如下......

    // 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;
     }
    
  • 149

    在C(但不是普通的C)中,只要两个定义完全相同,输入两次类型是完全合法的:

    // 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);
    
  • 41

    要“fwd声明一个typedef”,你需要fwd声明一个类或一个结构,然后你可以键入def声明的类型 . 编译器可以接受多个相同的typedef .

    长表:

    class MyClass;
    typedef MyClass myclass_t;
    

    简写:

    typedef class MyClass myclass_t;
    
  • 0

    因为要声明一个类型,需要知道它的大小 . 您可以转发声明指向该类型的指针,或者键入一个指向该类型的指针 .

    如果你真的想,你可以使用pimpl成语来保持包含下来 . 但是如果你想使用一个类型而不是指针,编译器必须知道它的大小 .

    编辑:j_random_hacker为这个答案添加了一个重要的限定条件,基本上需要知道使用该类型的大小,但是如果我们只需要知道类型是否存在就可以进行前向声明,以便创建指针或引用类型 . 由于OP没有编译,我假设(可能是正确的)OP试图使用该类型,而不仅仅是引用它 .

  • 0

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

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

    但是,无论指针对象的大小如何,编译器都知道指针或引用的大小,因此前向声明就足够了 - 它声明了一个类型标识符名称 .

    有趣的是,当使用指针或引用 classstruct 类型时,编译器可以处理不完整的类型,从而节省了转发声明指针类型的需要:

    // 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
    
  • 14

    我有同样的问题,不想在不同的文件中混淆多个typedef,所以我用继承解决了它:

    是:

    class BurstBoss {
    
    public:
    
        typedef std::pair<Ogre::ParticleSystem*, bool> ParticleSystem; // removed this with...
    

    做:

    class ParticleSystem : public std::pair<Ogre::ParticleSystem*, bool>
    {
    
    public:
    
        ParticleSystem(Ogre::ParticleSystem* system, bool enabled) : std::pair<Ogre::ParticleSystem*, bool>(system, enabled) {
        };
    };
    

    工作就像一个魅力 . 当然,我不得不改变任何引用

    BurstBoss::ParticleSystem
    

    简单地说

    ParticleSystem
    
  • 11

    正如Bill Kotsias所指出的那样,唯一合理的方法是保持你的点的typedef细节是私有的,并且转发声明它们是继承 . 你可以用C 11做得更好一些 . 考虑一下:

    // 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;
    };
    
  • 16

    就像@BillKotsias一样,我使用了继承,它对我有用 .

    我改变了这个混乱(它需要我声明中的所有提升 Headers * .h)

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

    进入这个声明(* .h)

    class VanillaAccumulator;
    std::unique_ptr<VanillaAccumulator> acc;
    

    并且实现(* .cpp)是

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

相关问题