以下代碼使用Visual Studio 2019編譯,但不使用gcc 和 clang 編譯。定義變數b會導致后兩個編譯器出錯。
#include <iostream>
class base
{
public:
constexpr base(int i) : m_i(i) {}
constexpr int i() const { return m_i; }
protected:
~base() = default; // Forbid polymorphic deletion
private:
const int m_i;
};
class derived final : public base
{
public:
constexpr derived() : base(42) {}
};
// Defining b compiles with Visual Studio 2019,
// but does not with gcc and clang.
// gcc 11.2: error: 'base::~base()' is protected within this context
// clang 13.0: error: variable of type 'const base' has protected destructor
constexpr base b(41);
// Defining d compiles with all 3 compilers.
constexpr derived d;
int main()
{
std::cout << b.i() << std::endl;
std::cout << d.i() << std::endl;
}
哪個編譯器是正確的?微軟,哪個編譯程式,或者gcc和clang,哪個沒有?
如果 gcc 和 clang 是正確的,為什么 b 會出現錯誤,而 d 卻沒有?
更新:
FWIW,如果我base進行如下更改,Visual Studio 2019也不會編譯程式:
class base
{
public:
constexpr base(int i) : m_i(i) {}
constexpr int i() const { return m_i; }
protected:
//~base() = default; // Forbid polymorphic deletion
// This does not compile with Visual Studio 2019 either.
~base() {}
private:
const int m_i;
};
但據我所知,默認的解構式和手動實作的解構式之間應該沒有區別,所以是的,我猜是 MS 編譯器中的一個錯誤。
uj5u.com熱心網友回復:
解構式是一個成員函式,因此不能在無法呼叫其他成員函式的背景關系中呼叫它。呼叫的背景關系是物件構造的背景關系(見下文),因此在您的情況下,您不能呼叫~base()外部base(或派生自 的類base),這就是為什么您會收到 gcc 和 clang(它們是正確的)。
[class.dtor#15] [...] 在每種情況下,呼叫的背景關系都是物件構造的背景關系。[...]
因為隱式宣告的解構式是公共的b,d所以出現錯誤而不是因為derived:
[class.dtor#2]如果一個類沒有用戶宣告的預期解構式,一個預期解構式被隱式宣告為默認的 ([dcl.fct.def])。隱式宣告的預期解構式是其類的行內公共成員。
將解構式設為baseprotected 或private 并不會默認將子類的解構式設為protected 或private,您只需獲得隱式定義的解構式,即public。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/356619.html
下一篇:~/和../之間的區別
