当定义成员函数时,哪些限定符必须出现在声明/定义/两者中
When defining a member function out-of-line, which qualifiers must appear in the declaration / definition / both?
我几乎可以肯定以前有人问过这个问题。不幸的是,我的C++已经变得如此生疏,以至于我甚至不知道该搜索什么。
有没有一条容易记住的经验法则可以告诉我,当我定义一个成员函数时,哪些限定符(inline
、virtual
、override
、const
、mutable
等)必须出现(a)仅在声明中,(b)仅在定义中,(c)同时出现在声明和定义中?
示例:
struct Geometry {
…
virtual Geometry* clone() const = 0;
};
struct Point2 : public Geometry {
…
virtual Point2* clone() const override { … }
};
如果我想将Point2::clone
定义为越界,试错会让我相信这将是正确的代码:
struct Point2 : public Geometry {
…
virtual Point2* clone() const override;
};
Point2* Point2::clone() const { … }
virtual
和override
限定符在声明中只能出现const
必须同时出现在声明和定义中
我不想永远依靠试错。但我想明确限定符(即重复它们,即使它们是由基类隐含的。)有没有一个通用规则,哪个限定符必须精确到哪里,或者每个限定符的规则不同?
一般规则是,当删除限定符产生不同的函数重载时,该限定符必须同时出现在两个位置。所有其他限定符都保留在声明中。
必须同时出现在这两个位置的三个限定符是const
和两种引用限定符,它们出现在C++11标准中:
void foo() const;
void foo() &;
void foo() &&;
所有其他限定符都保留在声明中。
了解哪些修饰符(或"说明符")必须在哪个实例中使用的最好方法是了解它们各自的含义和作用。
const
是该方法"签名"的一部分。签名包括函数返回的内容、参数的类型以及它是否是常量方法(const
部分)。这是不能改变的,必须保持原样
列表中的其他virtual
和override
都与方法的声明有关。它不是方法签名的一部分,只能出现在方法声明中。
唯一的经验法则(如果有的话)是,当方法没有内联定义时,作为方法签名一部分的任何东西都必须保持不变。如果不是,它必须只是声明的一部分(但是,就像所有经验法则一样,总是有一个例外,inline
关键字)。
请注意,默认参数值不被视为方法签名的一部分。只能在声明中指定默认参数值。但是,如果方法是内联定义的,那么默认参数值最终会成为方法定义的一部分!
我将采用另一种方法:我的经验法则:将它们放在两个位置,然后按照编译器的指示执行。它实现了标准规则,并将使您遵守这些规则。
任何经验法则的问题都是,你不能确定某个特定的例子是否正常,所以为什么不默认从一开始就检查呢。
如果你很少使用C++,那么学习一些无论如何都不能100%依赖的规则是没有意义的。如果你(开始)经常使用C++,那么在编译器多次告诉你该做什么之后,你就会自己得到要点。
因为这篇文章与其他文章的语气不一样,我会一直走无赖的路,用一个黑暗角落的例子给你这个非常不用的例子:显式实例化中的constexpr
template <class T>
constexpr auto foo(T)
{
}
template constexpr auto foo(int);
// ^
// 6 : error: explicit instantiation shall not use 'constexpr' specifier
这不是你所问的,但它表明你可以将这种策略应用于更广泛的类似问题,否则你需要其他拇指规则
- 如何确保C++函数在定义之前声明(如override关键字)
- 为什么在定义函数之前先声明它
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- Visual Studio中的函数声明和函数定义问题
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 如何在标头中声明(或定义)函数的问题
- 程序顶部的声明与定义(最佳实践)
- 类的前向声明之后的类成员函数定义,在类声明之前
- 静态变量声明和定义
- C++ G++ 编译器 - 错误:隐式声明的定义
- C++:错误重定义和先前声明
- 类模板静态数据成员定义/声明/初始化
- 只有一个定义/声明时标头声明变量的多堆定义错误
- OpenCV - Ptr 语法和类定义/声明 - 混淆?
- 如何为非类型模板类的专用化定义声明之外的方法
- 我如何防止静态类成员变量需要两个定义/声明
- 默认定义声明的详细程度不完整
- C++:非成员函数的定义/声明的位置
- 将比较操作符的重载定义/声明为库中的非成员函数
- C++头重新定义/声明混合