派生内部类的前向声明

时间:2013-10-29 15:19:07

标签: c++ inheritance compiler-errors inner-classes forward-declaration

我遇到了实施工厂方法的一些变化的问题。

// from IFoo.h

struct IFoo {

  struct IBar {
    virtual ~IBar() = 0;
    virtual void someMethod() = 0;
  };

  virtual IBar *createBar() = 0;
};

// from Foo.h 
struct Foo : IFoo { // implementation of Foo, Bar in Foo.cpp

  struct Bar : IBar { 
    virtual ~Bar();
    virtual void someMethod();
  };

  virtual Bar *createBar(); // implemented in Foo.cpp
};    

我想在Foo.cpp中声明Foo :: Bar的声明。现在我不能成功:

struct Foo : IFoo {

  //struct Bar;        //1. error: invalid covariant return type 
                       //   for ‘virtual Foo::Bar* Foo::createBar()’
  //struct Bar : IBar; //2. error: expected ‘{’ before ‘;’ token

  virtual Bar *createBar(); 
  // virtual IBar *createBar(); // Is not acceptable by-design
};    

是否有一个技巧可以在Boo中直接声明Foo.hpp并在Foo.cpp中进行完整声明?

编辑: 看起来,我没有显示错误。 S®,有更详细的样本。

  • 首次尝试前瞻声明:

    struct Foo : IFoo {
      struct Bar;        
      virtual Bar *createBar(); //<- Compile-error
    };
    //error: invalid covariant return type for ‘virtual Foo::Bar* Foo::createBar()’
    
  • 第二次尝试前瞻声明:

    struct Foo : IFoo {
      struct Bar : IBar; //<- Compile-error
      virtual Bar *createBar(); 
    };
    // error: expected ‘{’ before ‘;’ token
    
  • 有人可以提供更改createBar的退货类型(从BarIBar

    struct Foo : IFoo {
      virtual IBar *createBar(); 
    };
    

    但是,这种解决方法不能被设计

  • 接受

3 个答案:

答案 0 :(得分:1)

不,你不能转发声明某个子类。

当然,既然你要隐藏课程细节,你可以添加另一层次的间接。

struct IFoo {
  struct IBar {
    virtual ~IBar() = 0;
    virtual void someMethod() = 0;
  };

  virtual IBar *createBar() = 0;
};

// from Foo.h 
struct Foo : IFoo {

    struct Bar : IBar {};

    virtual Bar *createBar();
};    

// In Foo.cpp

struct FooBar : Foo::Bar
{
    virtual ~FooBar() {}
    virtual void someMethod() 
    {
        // Do stuff...
    }
};

Foo::Bar* Foo::createBar()
{
    return new FooBar;
}

答案 1 :(得分:0)

当然,您可以对嵌入式类进行前向声明。但是,只有实现文件Foo.cpp中才能访问Bar和IFoo :: IBar的关系。

foo.h中:

struct Foo : IFoo {

    struct Bar;

    virtual IBar *createBar();
};    

Foo.cpp中:

struct FooBar::Bar
{
    /* define the nested class here */
};

答案 2 :(得分:0)

您甚至不需要在Foo类中声明Bar子类型。栏可以完全隐藏在源文件中。

这个例子说明了我的意思:

#include <functional>
#include <iostream>
#include <utility>

struct IFoo {

  struct IBar {
    virtual ~IBar(){}
    virtual void someMethod() = 0;
  };

  virtual IBar *createBar() = 0;
};

// from Foo.h 
struct Foo : IFoo { // implementation of Foo, Bar in Foo.cpp


  virtual IBar *createBar(); // implemented in Foo.cpp
};    

namespace {
    struct HiddenBar : IFoo::IBar
    {
        virtual void someMethod(){
            std::cout<<"I am IBar type"<<std::endl;
        }
    };
}

IFoo::IBar* Foo::createBar()
{
    return new HiddenBar;
}


int main() {
    Foo foo;

    auto bar = foo.createBar();

    bar->someMethod();
}

请注意,HiddenBar应该对外界不可见,并且只能通过它的界面访问。但这意味着要修复Foo::createBar()方法的签名。

另一种方法是在Foo中完全声明Foo :: Bar。没有办法解决它。