是否可以重载阴影虚拟函数?

问题描述

我想隐藏基类的虚函数,并引入一个具有相同名称和相同签名的新虚函数,但返回类型除外。

类似于:

using Microsoft.AspNetCore.nodeservices;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace ConvertHighchart.Controllers
{
[ApiController]
[Route("[controller]")]
public class runNodeScriptController : ControllerBase
{
    private readonly Inodeservices _nodeservices;
    public runNodeScriptController(Inodeservices nodeservices)
    {
        _nodeservices = nodeservices;
    }

    [HttpPost]
    public async Task<IActionResult> Post()
    {
        var result = "";
        try
        {
            result = await _nodeservices.InvokeExportAsync<string>("test_nodejs_script","generateHighChart","abc");
        }
        catch (System.Exception ex)
        {
        }

        return Ok(result);
    }
  }
}

我希望它的行为方式如下:

struct A {
  virtual int f() = 0;              // Newly introduced method: A::f.
};
struct B: public A {
  int f() final { return 1; }       // Overriding A::f.
};
struct C: public B {
  virtual double f() = 0;           // Newly introduced method C::f. It shadows A::f
};
struct D: public C {
  double f() final { return 2.0; }  // Overriding C::f.
};

有可能实现吗?

任何版本的 C++ 标准都可以。

解决方法

如果不改变函数签名(返回类型不是它的一部分),重载是不可能的。但是由于默认函数参数,我们可以有不同的签名,但仍然使用相同数量的参数调用。使用 C++20 的 std::type_identity 之类的东西(尽管很容易在任何标准中实现),一旦可以编写

struct A {
  virtual int f(std::type_identity<int> = {}) = 0;
};
struct B: public A {
  int f(std::type_identity<int> = {}) final { return 1; }
};
struct C: public B {
  virtual double f(std::type_identity<double> = {}) = 0;
};
struct D: public C {
  double f(std::type_identity<double> = {}) final { return 2.0; }
};

现在每个重载都标有其返回类型,从而赋予每个重载不同的签名。但是默认参数 {} 可以通过 f() 调用它们。并且由于名称隐藏,空参数列表的重载集没有冲突。

通过这些修改,your set of assertions now passes

,

如果不让B直接继承E,而是引入同时继承BD的{​​{1}},你可以有不同的 f() 并用 static_cast 消除它们之间的歧义。

struct A {
  virtual int f() = 0;              // Newly introduced method: A::f.
};

struct B: public A {
  int f() override final { return 1; }       // Overriding A::f.
};

struct C {
  virtual double f() = 0;           // Newly introduced method C::f
};

struct D: public C {
  double f() override final { return 2.0; }  // Overriding C::f.
};

struct E : public B,public D { // inherit from both B and D
};
int main() {
    E foo;
    std::cout << static_cast<A&>(foo).f() << '\n'; // 1
    std::cout << static_cast<B&>(foo).f() << '\n'; // 1
    std::cout << static_cast<C&>(foo).f() << '\n'; // 2
    std::cout << static_cast<D&>(foo).f() << '\n'; // 2
}