我想用一些常用的功能和流畅的界面构建一个基类(抽象)类(让我们称之为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;
}
但我在想如何实施它,我没有找到任何有效的想法,一些建议?
答案 0 :(得分:5)
您应该返回引用/指针,并且您不需要保留类型信息。
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();
}
您已经有了一个虚拟析构函数。大概你有其他虚拟功能。通过基类型和在那里声明的虚函数访问所有内容。
答案 1 :(得分: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();
答案 2 :(得分:0)
一种解决方案可以这样工作:
return *static_cast<my_type*>(&my_type().with_foo().with_bar());
使用static_cast
基本上告诉编译器'我知道我在做什么'。
答案 3 :(得分:-1)
在C ++中,您应该返回指针或引用而不是值。此外,您可能想要解释“流畅的界面”的含义。
答案 4 :(得分:-2)
我在C#中这样做的方式,我相信它在C ++中也可以为with_foo()
和with_bar()
提供默认实现...原谅我的c#,但是:< / p>
class base {
virtual base with_foo()
{ throw new NotImplementedException(); }
virtual base with_bar();
{ throw new NotImplementedException(); }
}