【问题标题】:What is the reason of implicit virtual-ness propagation?隐式虚拟传播的原因是什么?
【发布时间】:2016-12-27 23:16:58
【问题描述】:

我使用 C++ 才 2~3 个月,最近我发现了标识符 final,它出现在虚函数之后。时至今日,我认为省略virtual会阻止虚拟性的传播,但我错了。它隐式传播。

我的问题是这样的。为什么允许隐式传播?为什么 virtual 的存在不能使函数虚拟,而 virtual 的存在不能使函数不虚拟?在某些情况下更好吗?还是在virtual首次推出的那一天?


根据Clifford's answer,甚至有一个编译器会在缺少virtual时生成警告。


why is the virtuality of methods implicitly propagated in c

我希望上面的链接能回答我的问题,但它没有。

------------ 加法-------------

有一些关于询问此功能的有用性的cmets。 我认为虚函数上的 final 关键字是对函数进行虚拟化的原因。该函数不能再被覆盖,因此派生类必须重新声明一个函数,无论它是否具有相同的名称。 如果 final 与去虚拟化不同,请帮我理解一下。 如果 final 没有什么不同,那么从引入 final 的事实来看,去虚拟化的用处是不言而喻的。 我同意强制显式 virtual 会产生错误,但我很好奇是否还有其他原因。

【问题讨论】:

  • 停止传播有什么用处并不明显。你有一个令人信服的例子吗? (请注意,final 比“在此处停止虚拟传播”要强大得多。)
  • @Sgene9 “无论我想去哪里”都不是有用的例子,更不用说令人信服了。发布一个具体情况并解释这将如何解决实际问题。
  • 如果vehicle->go() 调用Car::go() 而不是Toyota::go(),那会很混乱
  • 允许子类使相同的函数成为非虚拟函数将违反 liskov 替换原则。在这样做时,您会强制子类引入特殊的技巧,以在对其进行操作之前检查某物的类型,并引入不必要的复杂性和出错的机会。想象一下,如果您通过引用基类将对象传递给函数,结果调用的函数与您预期的不同。会很混乱!
  • 它不能用相同的签名声明 foo。这就是重点。它可以用不同的签名声明它,但不会被覆盖。

标签: c++ methods virtual propagation


【解决方案1】:

为什么特定功能存在(或不存在)的答案通常相当困难,因为它变成了猜测和意见的问题。但是,简单的答案可能是principle of least astonishment。想出一个有意义且工作可靠且可预测的方案是很困难的。

“去虚拟化”一个函数意味着什么?如果在运行时,您在对象上调用“去虚拟化”函数,它会改用指针的静态类型吗?如果静态类型有虚函数,而运行时类型没有,会发生什么?

#include <iostream>

struct A     {  virtual void f() const { std::cout << "A"; }  };
struct B : A {          void f() const { std::cout << "B"; }  };
struct C : B {  virtual void f() const { std::cout << "C"; }  };
struct D : C {          void f() const { std::cout << "D"; }  };

void f(const A& o) { o.f(); }

int main()
{
                // "devirtualized"     real C++

    f(A{});     // "A"                 "A"
    f(B{});     // "A" or "B"?         "B"
    f(C{});     // "C"?                "C"
    f(D{});     // oh god              "D"
}

还有一个事实是,对于绝大多数设计,虚函数必须在整个层次结构中保持虚拟。对所有这些都要求virtual 会引入各种难以诊断的错误。 C++ 通常会尽量远离那些需要纪律才能做到正确的功能。

【讨论】:

  • “C++ 通常会尽量远离那些需要纪律才能做到正确的特性”……嗯,直到你开始学习更多的语言,或者你从 C 世界进入它。然后它就崩溃了一点:P
  • @SebastianLenartowicz RAII、智能指针、更严格的类型系统、异常、可变参数模板,不胜枚举。你到底在说什么?
  • 我的意思是,确实如此。我只是认为 C++(不要误会,我喜欢它)有很多小“陷阱”,如果你没有准备好的话。
  • @isanae f( A ) = "A" f( B ) = "A" f( C ) = "C" f( D ) = "C" struct A 声明了一个虚函数,struct B继承了A,struct C继承了B但是由于B::f()不是虚函数,C声明了另一个虚函数,struct D继承了C
  • struct A { virtual void f() const { std::cout
猜你喜欢
  • 2012-12-07
  • 1970-01-01
  • 2017-04-10
  • 2012-06-15
  • 2018-08-12
  • 2016-11-14
  • 2011-04-18
  • 2020-04-13
相关资源
最近更新 更多