隐式虚拟性传播的原因是什么?
What is the reason of implicit virtual-ness propagation?
我只使用 C++ 工作了 2~3 个月,最近我发现了标识符 final,它位于虚函数之后。直到今天,我还相信省略 virtual 会阻止虚拟性的传播,但我错了。它隐式传播。
我的问题是这样的。为什么允许隐式传播?为什么 virtual 的存在不能使函数成为虚函数而 virtual 的存在不能使函数不是虚函数?在某些情况下更好吗?还是在首次引入 虚拟 的那一天?
根据 Clifford's answer,甚至有一个编译器会在缺少 virtual.
时生成警告
why is the virtuality of methods implicitly propagated in c
我希望上面 link 能回答我的问题,但没有。
------------加法------------
有评论询问此功能的用处。
我认为虚函数上的 final 关键字是使函数去虚拟化的原因。该函数不能再被覆盖,因此派生的 class 必须重新声明一个函数,无论它是否具有相同的名称。
如果 final 与去虚拟化不同,请帮助我理解它。
如果 final 没有什么不同,那么从引入 final 的事实来看,去虚拟化的用处是不言而喻的。
我同意强制显式 virtual 会产生错误,但我很好奇是否还有其他原因。
关于为什么某个特定功能存在(或不存在)的答案通常相当困难,因为它变成了猜测和意见的问题。然而,简单的答案可能是 principle of least astonishment。想出一个合理且可靠地工作并且可预测的方案将是困难的。
"devirtualizing" 函数甚至意味着什么?如果在运行时,您在对象上调用 "devirtualized" 函数,它会使用指针的静态类型吗?如果静态类型有虚函数但运行时类型没有,会发生什么?
#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++ 工作了 2~3 个月,最近我发现了标识符 final,它位于虚函数之后。直到今天,我还相信省略 virtual 会阻止虚拟性的传播,但我错了。它隐式传播。
我的问题是这样的。为什么允许隐式传播?为什么 virtual 的存在不能使函数成为虚函数而 virtual 的存在不能使函数不是虚函数?在某些情况下更好吗?还是在首次引入 虚拟 的那一天?
根据 Clifford's answer,甚至有一个编译器会在缺少 virtual.
时生成警告why is the virtuality of methods implicitly propagated in c
我希望上面 link 能回答我的问题,但没有。
------------加法------------
有评论询问此功能的用处。 我认为虚函数上的 final 关键字是使函数去虚拟化的原因。该函数不能再被覆盖,因此派生的 class 必须重新声明一个函数,无论它是否具有相同的名称。 如果 final 与去虚拟化不同,请帮助我理解它。 如果 final 没有什么不同,那么从引入 final 的事实来看,去虚拟化的用处是不言而喻的。 我同意强制显式 virtual 会产生错误,但我很好奇是否还有其他原因。
关于为什么某个特定功能存在(或不存在)的答案通常相当困难,因为它变成了猜测和意见的问题。然而,简单的答案可能是 principle of least astonishment。想出一个合理且可靠地工作并且可预测的方案将是困难的。
"devirtualizing" 函数甚至意味着什么?如果在运行时,您在对象上调用 "devirtualized" 函数,它会使用指针的静态类型吗?如果静态类型有虚函数但运行时类型没有,会发生什么?
#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++ 通常会尽量避免使用需要纪律才能正确使用的功能。