2016-05-13 33 views
3

我已經建立了以下小例子:轉換的虛假通過爲const char對象*構造

class A 
{ 
    public: 
     A(const char *s); 

    private: 
     const char *p; 
}; 

A::A(const char *s) 
    : p(s) 
{ 
} 

A foo() 
{ 
    return false; 
} 

A bar() 
{ 
    return true; 
} 

g++ (Debian 4.7.2-5) 4.7.2編譯,我得到以下幾點:

t.cc: In function 'A foo()': 
t.cc:17:10: warning: converting 'false' to pointer type for argument 1 of 'A::A(const char*)' [-Wconversion-null] 
t.cc: In function 'A bar()': 
t.cc:23:10: error: could not convert 'true' from 'bool' to 'A' 

據我所知,如果類A具有構造函數A(T),則可以使用一個類型T而不是類A的實例。在這種情況下,編譯器在調用A(T)構造函數時將T的值/實例包裝在內。

此外,只有一個直接隱式轉換是允許的,即,沒有鏈A(B(c))被插入到一個值c轉換C類型的,即使構造A(B)B(C)存在。

所以,我的問題:

  1. 爲什麼false轉換爲在我的例子指針?當然,一個指針不是一個對象,但是這裏仍然有兩個隱式轉換。什麼規則正在應用?
  2. 爲什麼轉換不適用於true?我的直覺是,false可以合理地轉換爲nullptr(另請參閱警告),而true沒有有意義的指針值。

那麼,有人能解釋哪些轉換規則適用/不適用於上述兩個示例?

+0

您的假設是正確的。所有的零值整數對象(「bool」和「char」都屬於)可以隱式轉換爲「nullptr」。這就是爲什麼'int * x = 0;'(和'int * x ='\ 0';')有效,但是'int * x = 1;'不。 –

+0

真的好問題! – Destructor

回答

5

正如公佈的那樣,C++ 11的規則是「整數類型的整型常量表達式prvalue,其求值爲0可以轉換爲任何指針類型,從而產生該類型的空指針值。 (C++ 98/03有一個相似的措辭規則,具有相同的淨效應)。

bool是整數類型,並且false評估爲0。所以false是一個有效的空指針常量。

除了這個額外的規則,C++沒有從整型到指針的隱式轉換。這就是爲什麼true不能隱式轉換爲指針。

但是,C++ 14更改了空指針常量的定義,以便只有整數文字(而不是整型常量表達式)有效。 false是一個布爾文字,不是一個整數,所以在C++ 14下,代碼不會編譯。此外,由於該問題已被標準委員會認定爲C++ 11中的缺陷,因此較新的C++ 11編譯器很可能在這方面遵循C++ 14規則,並且不會將false視爲空值指針常量。感謝@Destructor追蹤issue status


至於爲什麼在這裏允許兩個隱式轉換:規則不是「最多允許一個隱式轉換」。該規則是「最多允許一個用戶定義的轉換。「指針轉換(例如將空指針常量轉換爲空指針值)不會被歸類爲用戶定義的轉換。因此,您的情況下的轉換序列是指針轉換(boolconst char *),然後是用戶定義的轉換( 。const char *A

+0

對於只允許一個隱式轉換的規則呢?在我的第一個例子中,它們有兩個:布爾型爲const char *的布爾型,以及爲A型的const char *。 – Giorgio

+0

是否將'false'視爲空指針常量? – Giorgio

+1

@Giorgio是的,正如答案所述。它是一個整數類型的值(與整數類型同義),其值爲'0'。 – Angew

0

對於1),falsebool型的,並且它可以是promotedint隱含:

  • 類型bool可以轉換爲int用叔他看到false變成0true變成1

所以,false基本上被提升爲NULL/0(或nullptr),其可以被分配到的指針。

對於2),§4.10指出:

空指針常數是文字(2.14.2)與零值或類型的std的prvalue :: nullptr_t的整數。可以將空指針常量轉換爲指針類型; [...]

只有Null pointer constant可以轉換爲一個指針,和一個空指針常數或者是一個可積具有值0std::nullptr_ttrue(或1)沒有被指定,因此它們不能被轉換爲指針。

+0

對於虛假是布爾和充滿恐懼 –

+0

@光我沒有得到你的觀點 – Rakete1111

+0

不要擔心:) –

2

當使用-std=c++11,-std=c++14時,OP的程序無法編譯g ++ &。

在g ++ 6.1.0上查看現場演示here。它給出以下錯誤

prog.cc: In function 'A foo()': 
prog.cc:17:12: error: could not convert 'false' from 'bool' to 'A' 
    return false; 
      ^~~~~ 

查看實況演示here關於鏗鏘聲++。它給出了以下診斷。

main.cpp:17:12: error: no viable conversion from returned value of type 'bool' to function return type 'A' 
    return false; 
      ^~~~~ 
main.cpp:1:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'bool' to 'const A &' for 1st argument 
class A 
    ^
main.cpp:1:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'bool' to 'A &&' for 1st argument 
class A 
    ^
main.cpp:10:4: note: candidate constructor not viable: no known conversion from 'bool' to 'const char *' for 1st argument 
A::A(const char *s) 
^
main.cpp:22:12: error: no viable conversion from returned value of type 'bool' to function return type 'A' 
    return true; 
      ^~~~ 
main.cpp:1:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'bool' to 'const A &' for 1st argument 
class A 
    ^
main.cpp:1:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'bool' to 'A &&' for 1st argument 
class A 
    ^
main.cpp:10:4: note: candidate constructor not viable: no known conversion from 'bool' to 'const char *' for 1st argument 
A::A(const char *s) 
^
main.cpp:7:21: warning: private field 'p' is not used [-Wunused-private-field] 
     const char *p; 
        ^

不應該轉換爲指針類型,因爲C++ 11。查看我曾經問過的類似問題here