给出这个人为的例子:
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
,那么我们又回到了原来的状态问题。
最佳答案
您正在寻找的是 Named Parameter Idiom ,我正在从 this StackOverflow answer 复制.不是返回对实际对象的引用,而是返回对特殊参数对象的引用,并依靠异常对象的构造函数在填充所有参数后进行隐式转换。这非常聪明,真的。
关于C++ 成员函数链接返回类型和派生类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5019850/