我们可以在基类中声明一个具有相同签名但返回类型不同的函数吗?

时间:2011-07-01 12:41:04

标签: c++

问题可能看起来很傻,但我想问......          有没有什么方法可以在具有相同签名但不同返回类型的类中声明一个方法(如int fun(int)和float fun(int)),并且在对象创建期间我们可以动态地决定要执行哪个函数!我有编译错误...有没有其他方法来实现这个逻辑可能是使用模板...

3 个答案:

答案 0 :(得分:7)

您始终可以将返回值作为模板。

template<typename T> T fun(int);
template<> float fun<float>(int);
template<> int fun<int>(int);

您可以在运行时动态决定调用哪个?否。

答案 1 :(得分:0)

@DeadMG提出了基于模板的解决方案,但是你可以简单地“调整”签名(可以说是模板参数的作用)。

这个想法只是添加一个伪参数:

struct Foo
{
  float fun(float); // no name, it's a dummy
  int fun(int);     // no name, it's a dummy
};

然后执行:

int main() {
  Foo foo;
  std::cout << foo.fun(int()) << ", " << foo.fun(float());
}

这可以完全用作模板解决方案(即从模板方法调用),但更容易拉动:

  • 少罗嗦
  • 函数模板特化应该在类外定义(虽然VC ++会在类中接受内联定义)

我更喜欢避免使用函数模板特化,一般来说,与参数的专门化一样,选择正确的重载/特化的规则很棘手。

答案 2 :(得分:0)

您可以(但不应该 * )使用重载转换运算符的代理类。

实际用例 *

的长例

让我以Dot & Cross Product Notation

为例

[...]

还有可能为dot-product和cross-product设置operator *。

假设一个基本的矢量类型(仅用于演示):

struct Vector {  
         float x,y,z;  
         Vector() {}  
         Vector (float x, float y, float z) : x(x), y(y), z(z) {}  
}; 

我们观察到点积是标量,交叉积是矢量。在C ++中,我们可能会重载转换运算符:

struct VecMulRet {
public:
        operator Vector ()  const {
                return Vector (
                        lhs.y*rhs.z - lhs.z*rhs.y,
                        lhs.z*rhs.x - lhs.x*rhs.z,
                        lhs.x*rhs.y - lhs.y*rhs.x
                );
        }
        operator float () const {
                return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
        }
private:
        // make construction private and only allow operator* to create an instance
        Vector const lhs, rhs;

        VecMulRet (Vector const &lhs, Vector const &rhs)
        : lhs(lhs), rhs(rhs)
        {}

        friend VecMulRet operator * (Vector const &lhs, Vector const &rhs);
};

只允许operator *使用struct VecMulRet,禁止复制VecMulRet(首先是偏执狂)。

运算符*现在定义如下:

VecMulRet operator * (Vector const &lhs, Vector const &rhs) {
        return VecMulRet (lhs, rhs);
}

Et瞧,我们可以写:

int main () {
        Vector a,b;
        float dot = a*b;
        Vector cross = a*b;
}
不过,这是由1999年制定的神圣标准所祝福的。

如果您在该主题中进一步阅读,您将找到一个基准测试,确认这不会导致性能损失。

演示 *

的简短示例

如果这太难掌握,那就是一个更为实际的例子:

struct my_multi_ret {
    operator unsigned int() const { return 0xdeadbeef; }
    operator float()        const { return 42.f;       } 
};

my_multi_ret multi () {
    return my_multi_ret();
}

#include <iostream>
#include <iomanip>
int main () {
    unsigned int i = multi();
    float f = multi();
    std::cout << std::hex << i << ", " << f << std::endl;
}

* 您可以,但不应该,因为它不符合最少惊喜的原则,因为它不是常见做法。不过,这很有趣。