9

我想构建一个type::base具有一些通用功能和流畅接口的基础(抽象)类(我们称之为),我面临的问题是所有这些方法的返回类型

  class base {
    public:
       base();
       virtual ~base();

       base& with_foo();
       base& with_bar();
    protected:
       // whatever...
  };

现在我可以制作子类型,例如:

  class my_type : public base {
    public:
      myType();        
      // more methods...
  };

使用这样的子类型时会出现问题:

 my_type build_my_type()
 {
    return my_type().with_foo().with_bar();
 }

这不会编译,因为我们返回的是 base 而不是 my_type。

我知道我可以:

 my_type build_my_type()
 {
    my_type ret;
    ret.with_foo().with_bar();

    return ret;
 }

但是我在想如何实现它,但我没有找到任何有效的想法,一些建议?

4

5 回答 5

4

这个“丢失类型”的问题可以用模板来解决——但它相当复杂。

例如。

class Pizza
{
  string topping;
public:
  virtual double price() const;
};

template <class T, class Base>
class FluentPizza : public Base
{
  T* withAnchovies() { ... some implementation ... };
};

class RectPizza : public FluentPizza<RectPizza, Pizza>
{
  double price() const { return length*width; :) }
};

class SquarePizza : public FluentPizza<SquarePizza, RectPizza>
{
   ... something else ...
};

然后你可以写

SquarePizza* p=(new SquarePizza)->withAnchovies();

模式是,而不是

class T : public B

你写

class T : public Fluent<T, B>

另一种方法可能是不在对象上使用流利的接口,而是在指针上使用:

class Pizza { ... };
class RectPizza { ... };
class SquarePizza { ... whatever you might imagine ... };

template <class T>
class FluentPizzaPtr
{
  T* pizza;
public:
  FluentPizzaPtr withAnchovies() {
    pizza->addAnchovies(); // a nonfluent method
    return *this;
  }
};

像这样使用:

FluentPizzaPtr<SquarePizza> squarePizzaFactory() { ... }

FluentPizzaPtr<SquarePizza> myPizza=squarePizzaFactory().withAnchovies();
于 2009-06-24T22:59:34.197 回答
4

您应该返回引用/指针,并且您不需要保留类型信息。

class base {
  public:
     base();
     virtual ~base();

     base &with_foo();
     base &with_bar();
  protected:
     // whatever...
};

class my_type : public base {
  public:
    my_type();        
    // more methods...
};

base *build_my_type()
{
   return &new my_type()->with_foo().with_bar();
}

您已经有一个虚拟析构函数。大概您还有其他虚拟功能。通过基类型和在那里声明的虚函数访问所有内容。

于 2009-06-25T00:21:29.193 回答
0

一种解决方案是这样工作的:

return *static_cast<my_type*>(&my_type().with_foo().with_bar());

Usingstatic_cast基本上告诉编译器'我知道我在这里做什么'。

于 2009-06-24T22:55:32.520 回答
-1

在 C++ 中,您应该返回指针或引用而不是值。此外,您可能想解释“流畅的界面”是什么意思。

于 2009-06-24T22:50:05.743 回答
-2

我在 C# 中执行此操作的方式,并且我相信它也可以在 C++ 中工作,是为with_foo()and提供默认实现with_bar()......请原谅我的 c#,但是:

class base {
  virtual base with_foo()
  { throw new NotImplementedException(); }
  virtual base with_bar();
  { throw new NotImplementedException(); }
}
于 2009-06-24T22:42:30.737 回答