虚函数重写基类函数

问题描述 投票:0回答:2
class foo
public:
void virtual ABC () throw(int,double,long);
};

参考上面的示例代码,如果派生类 bar 重写了方法 ABC,则以下哪一项是可接受的声明。

void ABC() throw(double,int,long);
void ABC();
int ABC ()throw(int,int,double).
int ABC()throw(int , double ,long)
void ABC()throw(string)

这个问题的答案`

c++ inheritance virtual
2个回答
0
投票

首先:动态异常规范自 C++11 起已被弃用,并自 C++17 起被删除(如注释中所示),请参见例如cpp参考

仍然假设有一个足够旧的标准(至少在 C++17 之前,在 C++11 之前,因为不依赖于已弃用的功能),然后思考:如果派生类抛出一个新的异常,而基类不会抛出,那么覆盖函数与基类版本不兼容(考虑指向持有派生实例的基类的指针 - 通过基接口,用户被承诺只需考虑一组给定的异常,而派生类将违反此承诺)。因此任何新抛出的类型都是非法的。

另一方面:如果一个函数可能会抛出一些东西,但实际上并没有这样做,那完全没问题。因此在覆盖函数中从异常列表中删除某些类型仍然符合原始签名,因此是合法的。

抛出类型的顺序实际上无关紧要,该子句只是声明可以抛出任何类型(当然实际上一次只能抛出一个)。从技术上讲,重复的类型也没关系,我不知道标准中明确禁止它的短语(并且上面的链接没有说明任何内容),所以它们应该没问题,尽管不会让我的手着火对于;)

考虑返回类型:对于一般情况,请查看协变返回类型(或一般的协变和逆变)——简而言之,这意味着您可以在派生类中返回更窄的类型(通过引用或指针) .

但这不适用于

void
int
!返回值预计将通过某种方式进行处理 - 派生类现在强加了使用基类指针的人永远无法满足的期望。此外,如果返回值需要在堆栈上为返回值保留空间,那么还存在一些技术问题;这必须针对派生类的版本完成,但对于基类的版本则不然,因此我们得到不兼容的堆栈要求(排除了忽略额外返回的内容不会造成伤害的论点……) .

考虑到所有这些,您很快就会发现哪些覆盖实际上是合法的:只有前两个。


0
投票

上面问题的答案是。 无效ABC();

© www.soinside.com 2019 - 2024. All rights reserved.