2

我在实现工厂方法的一些变体时遇到了问题。

// 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::Bar 的声明放在Foo.cpp. 现在我不能成功:

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

是否有一个技巧来提前声明BooinFoo.hpp和完整声明 in Foo.cpp

编辑:看起来,我没有清楚地显示错误。所以,有更详细的样本。

  • 第一次尝试前向声明:

    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(from Barto IBar)的返回类型

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

    但是,这种解决方法在设计上是不可接受的

4

3 回答 3

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;
}
于 2013-10-29T15:51:35.700 回答
0

您甚至不需要在 Foo 类中声明 Bar 子类型。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。没有办法解决它。

于 2013-10-29T16:21:36.490 回答
0

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

富.h:

struct Foo : IFoo {

    struct Bar;

    virtual IBar *createBar();
};    

Foo.cpp:

struct FooBar::Bar
{
    /* define the nested class here */
};
于 2013-10-29T16:00:27.443 回答