是否有一种使用其他运算符扩展类的好方法?

时间:2016-05-28 07:09:34

标签: c++ inheritance operator-overloading

我遗漏了std::complex的一些重要功能,例如添加std::complex<float>std::complex<double>1+c之类的操作,即int之间的操作和std::complex。我的想法是从my::complex派生一个新类std::complex,它只是继承已经实现的所有内容并添加其他内容。

为了使代码与使用std::complex的函数兼容,我添加了std::complex的自动转换(以及my::complex<float>my::complex<double>之间的自动转换)。

现在像

my::complex<float> c1,c2,c3;
c1 = c2 + c3;

虽然我自己没有实现operator+,但是c2c3被强制转换为std::complex,然后添加并将结果转换回my::complex }。我假设编译器可以优化任何实际的复制。

但是,以下情况不起作用:

c1 = 2*(c2+c3)

因为std::complex不能乘以一个整数(如果我乘以一个double并且有complex<float> s则会出现同样的问题。)

我想&#34;好吧,似乎我必须在{#1}之后添加operator+,但如果我这样做,我得到use of overloaded operator '+' is ambiguous,因为编译器可以在{{1}之间}}和std::complex含蓄地。

有没有更好的方法来实现我想要或做的事情我需要完全重新实现my::complex中的所有内容并抛弃继承?

2 个答案:

答案 0 :(得分:7)

将这些重载添加为自由函数可能与完成任何工作一样好。但是,我不会为每对可能的操作数类型编写一个单独的硬编码 - 这会很快变得乏味。

相反,你无疑想要编写一个模板函数来处理任何一对操作数类型。关于这个一般顺序的东西:

template <class T, class U>
auto operator*(T const &a, U const &b) -> typename std::common_type<T, U>::type 
{
    // code to produce the equivalent of: return a * b;
}

这样,如果您将complex<double>乘以int而将complex<float>乘以double(等),则不必复制该函数对于每种可能的组合(如果您尝试组合两种不具有共同类型的类型,例如complex<double>std::string,则它只是不会编译)。

在这种情况下,填充正文非常简单:我们有两种不同类型的输入,但我们知道(或可以推断)与两者兼容的常见类型。我们希望将每个输入转换为该公共类型,并对转换结果执行操作:

template <class T, class U>
auto operator*(T const &a, U const &b) -> typename std::common_type<T, U>::type 
{
    using ret_type = typename std::common_type<T, U>::type;
    return ret_type(a) * ret_type(b);
}

答案 1 :(得分:6)

为了添加复杂数量的不同类型和其他运算符,我将使用自由函数

std::complex<double> operator? (std::complex<double> a,std::complex<float> b){
    std::complex<double> result;
    // implement ?
    return result;
}
std::complex<double> operator? (std::complex<float> a,std::complex<double> b){
    return b ? a;
}

其中?是您想要的运营商的地方。请注意,这是一个pre-C ++ 11解决方案,更好的方式请参阅Jerry Coffins answer

为了向复合体添加数字,例如在1+c中,我不会努力编写运算符,而只需使用c+1代替(实际上我不确定这是否适用于{ {1}}但如果不是,我会感到惊讶)。