鉴于这种人为的例子:C++成员函数链接返回类型和派生类
struct point_2d {
point_2d& x(int n) {
x_ = n;
return *this;
}
point_2d& y(int n) {
y_ = n;
return *this;
}
int x_, y_;
};
struct point_3d : point_2d {
point_3d& z(int n) {
z_ = n;
return *this;
}
int z_;
};
int main() {
point_3d p;
p.x(0).y(0).z(0); // error: "point_2d" has no member named "z"
return 0;
}
的想法是使用“成员函数链”,以便能够调用多个成员函数在一排。 (有很多这样的例子,上面是我能想到的最短的一个,用于提出这个问题,我的实际问题是类似的,下面会有描述。)
问题是如果派生类增加它自己的链接成员函数,但是你首先调用一个基类的成员函数,你会得到一个基类引用,当然这对于调用派生类的成员函数来说是无效的。
有没有什么聪明的方法来解决这个问题,仍然保持成员函数链接的能力?
企业的实际问题
我实际问题是,我的基类是个例外,我的派生类是从基本异常派生的类。对于这些类也,我想使用成员函数链接:
class base_exception : public std::exception {
// ...
base_exception& set_something(int some_param) {
// ...
return *this;
}
};
class derived_exception : public base_exception {
// ...
};
int main() {
try {
// ...
if (disaster)
throw derived_exception(required_arg1, required_arg2)
.set_something(optional_param);
}
catch (derived_exception const &e) {
// terminate called after throwing an instance of 'base_exception'
}
}
的问题是,set_something()
回报base_exception
但catch
期望一个derived_exception
。当然,一个人类可以告诉,异常的实际类型是derived_exception
,但编译器显然不能说。
这就是我真正想要解决的问题,即如何让基本异常类能够在异常对象上设置可选参数,然后返回派生类型的实例。上面给出的point_2d
例子是(我相信)人们理解的同一个问题的一个更小和更简单的版本,并且小问题的解决方案也将解决我的实际问题。
请注意,我没有考虑做base_exception
模板,并在派生类传似:
template<class Derived>
class base_exception {
// ...
Derived& set_something(int some_param) {
// ...
return *this;
}
};
我相信事实并解决问题,但它不是一个完美的解决方案,因为如果其他类more_derived_exception
导出从derived_exception
,那么我们又回到了同样的问题。
的`base_exception <类派生>你有你的问题的最后是被称为奇异递归模板模式(CRTP)`想法。我认为它不会为您的情况提供解决方案,因为您的异常层次结构中无法使用单个根基类。 – 2011-02-16 17:43:14
@艾米尔:是的,我说这不是一个完美的解决方案,为什么。 – 2011-02-16 17:54:44
我只是指出,为了其他读者的利益,你显示的模式有一个特定的名称。我还给出了另一个原因,为什么(不同于你的)解决方案不起作用。我不打算批评你。 :-) – 2011-02-16 19:46:17