在c++ /CLI中,当存在多个重载时,我如何选择要覆盖的方法

本文关键字:何选择 选择 覆盖 方法 CLI c++ 存在 重载 | 更新日期: 2023-09-27 18:17:32

在c#项目中,我有一些类型如下:

public struct Struct<T> { public T Field; }
public interface IInterface<T>
{
    T F(T x);
}
public abstract class Class<T> : IInterface<T>, IInterface<Struct<T>> {
    virtual public T F(T x) { return x; }
    virtual public T F(Struct<T> x) { return x.Field; }
    Struct<T> IInterface<Struct<T>>.F(Struct<T> x) { return default(Struct<T>); }
}

在c++/CLI项目中,我想从Class<T>继承并覆盖虚拟F方法:

public ref class Derived sealed : public Class<int> {
public:
    virtual int F(Struct<int> x) override;
};

不幸的是,这不起作用:

error C2553: 'int Derived::F(Struct<T>)': overriding virtual function return type
differs from 'Struct<T> IInterface<Struct<T>>::F(Struct<T>)'
with
    [
        T=int
    ]

所以看起来编译器想要覆盖显式接口实现而不是虚方法。

我已经尝试了几种变化,但没有一个工作。有时我只是得到

error C3671: 'Derived:F' : function does not override 'IInterface<T>::F'

如何指定要重写的正确方法?

如果我添加IInterface::F的显式接口实现,就像Ken下面建议的那样,那么错误消息就会消失。

看起来这是c++/CLI编译器的错误:我不应该重新实现接口。

不幸的是,虽然这是一个很好的解决方法,但问题并没有完全解决:

如果我调用Derived::F作为IInterface,则调用Derived的显式实现(IInterface_F)。如果我可以将调用从基类传递给实现,那么作为一种变通方法,这是很好的。

所以我接下来的问题是:如果我有一个具有相同签名的重载(除了返回类型),并且在派生类中定义相同接口的显式实现,我如何从基类调用显式接口实现?

换句话说,如果我在c#中有:

public interface IInterface {
    int F(int x);
}
public class A : IInterface {
    virtual long F(int x) { return 1L; }
    int IInterface.F(int x) { return 3; }
}

和c++/CLI中的

public ref class B : A {
public:
    virtual long F(int x) override { return 2L; }        
    virtual int IInterface_F(int x) sealed = IInterface::F {
        return ??? // call A's version of IInterface::F(x), which returns three
    }
}

如何从IInterface_F调用AIInterface::F版本?

在c++ /CLI中,当存在多个重载时,我如何选择要覆盖的方法

使用您提供的代码(尽管Class<T>对我来说看起来很奇怪):

public ref class Derived sealed : public Class<int> {
public:
    virtual int F(Struct<int> x) override;
};

编译器报错:

错误C2553: 'int Derived::F(Struct)':重写虚函数返回类型不同于'Struct IInterface>::F(Struct)'

与[T = int]

错误C3766: 'Derived'必须提供接口方法'Struct IInterface>::F(Struct)'

的实现与[T = int]

错误C3612: 'Derived':一个密封类不能有任何纯虚方法必须定义以下方法:

Struct IInterface>::F(Struct)':是抽象的与[T = int]

所以我认为提供接口方法的实现就像编译器说的那样正好解决了问题:

public ref class Derived sealed : public Class<int> {
public:
    virtual Struct<int> IInterface_F(Struct<int> x) 
        sealed=IInterface<Struct<int>>::F {
        return Struct<int>(); // equivalent to default(Struct<int>) in c#
    }
    virtual int F(Struct<int> x) override {
        return 0; // equivalent to default(int) in c#
    }
};