2009-05-15 41 views
23

Son yayınlanan bir cevabın, What other useful casts can be used in C++ hakkındaki birkaç yorum, C++ dönüşümleri anlayışımın hatalı olduğunu ortaya koymaktadır.C++ örtük dönüşümler

#include <string> 

struct A { 
    A(const std::string & s) {} 
}; 

void func(const A & a) { 
} 

int main() { 
    func("one");     // error 
    func(A("two"));   // ok 
    func(std::string("three")); // ok 
} 

Benim iddiası bir dönüşüm elde var bir A'ya bir const char * dan dönüşüm yaşanmaz becauuse ilk işlev çağrısı bir hata olduğunu idi: Sadece konuyu netleştirmek için, aşağıdaki kodu dikkate Bir A'ya bir dize, ancak bunu kullanarak birden fazla dönüşüm içerebilir. Benim anlayışım buna izin verilmiyor ve bu g ++ 4.4.0 & Comeau derleyiciler tarafından onaylanmış gibi görünüyor. Comeau ile aşağıdaki hatayı alıyorum: Yanlış nerede olduğumu tercihen C++ Standard atfen, ya burada ya da orijinal cevap, işaret Eğer

"ComeauTest.c", line 11: error: no suitable constructor exists 
     to convert from "const char [4]" to "A" 
     func("one");     // error 

, lütfen bunu.

Ve C++ standardından cevap gibi görünüyor: Abhay için

At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

Teşekkür alıntı sağlamak için.

+0

Üzgünüm, cevabınıza yapılan yorumlarda yanılmışım. "Aşırı yükleme çözünürlüğü, çağrılacak kullanıcı tanımlı dönüştürmeyi seçmek için kullanılır." Dedim ve kendime 'iyi' dedim, sonra A (string const &) 'a ve "one"' a geçecek, ama tamamen başarısız oldum 13.3.3.1.2'nin ne dediğini düşünmek için: "Kullanıcı tanımlı bir dönüşüm dizisi, bir standart standart dönüşüm dizisinden ve bir kullanıcı tanımlı dönüştürme (12.3) ve ardından ikinci bir standart dönüşüm dizisinden oluşur." Ancak "bir" -> dizgesi standart bir dönüşüm dizisi olmayacak, ancak başka bir kullanıcı tanımlı dönüşüm dizisi gerektirecektir! –

+0

Mermerlerimi kaybetmediğim sürece sadece… –

+0

Harika soru! Tartışma, “std :: string” inin dilin bir parçası olmadığını ve “kullanıcı tanımlı” olduğu/dönüştürüldüğünü ima eder. En azından bu benim anlayışım, eğer yanılıyorsam beni düzeltin. Sorunun daha açık olması güzel olurdu. Std :: string'in tam durumu, eski C++ ellerine kristal berraklığında olabilir, ancak bu yüzyılda dile gelen insanlar için fark etmek kolay değildir. –

cevap

12

Keskin dişlerden gelen cevabın hassas olduğunu düşünüyorum. 'Dönüşümler' başlıklı 12.3.4 numaralı C++ Standardı (SC22-N-4411.pdf), yalnızca tek bir örtük kullanıcı tanımlı dönüşüme izin verildiğini açıkça belirtir.

1 Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (Clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9).

2 User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2). Conversions obey the access control rules (Clause 11). Access control is applied after ambiguity resolution (3.4).

3 [ Note: See 13.3 for a discussion of the use of conversions in function calls as well as examples below. —end note ]

4 At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single value.

+0

kitabında, belirli bir senaryoda örtük dönüşümler kullanmanın neden zevk aldığımı hissetmeye mecbur hissediyorum: yani, değişkende ilgili işlevleri gerçekleştiren bir sınıfla basit bir tipte bir değişkeni çiftlemek istediğimde. Implicit dönüşüme ek olarak, std :: string'in c_str() işlevini sağladığı şekilde, değeri döndüren sınıfta bir işlev sağlarım. Daha sonra ihtiyaç duyulduğunda ekstra sınıf işlevselliğine sahip olabilirsiniz ve ilgili işlevselliği bir arada tutarken, başka yerlere de çok hafif gidebilirsiniz. – moodboom

8

Bu doğru, yalnızca bir örtük dönüşüme izin verilir.

Üst üste iki dönüşüm, bir dönüşüm işleci ile parametreli bir yapıcıdan oluşan bir kombinasyonla gerçekleştirilebilir, ancak bu, C4927 warning - "yasa dışı dönüştürme; birden çok kullanıcı tanımlı dönüştürmenin örtük olarak uygulandığı" - VC++ için sebep.

5

The C++ Programming Language (4. Ed.) (bölüm 18.4.3) diyor bazı yerli arasındaki değilseniz "kullanıcı tanımlı" kısmı birden çok örtük dönüşümler gibi ses yapar izin verilebilir Yani

only one level of user-defined implicit conversion is legal

türleri.

+0

+1 son alıntıdan alıntı için. Stroustrup kitabının – mloskot

9

Mutabakat zaten olduğu gibi: evet haklısınız.

Ancak bu soru/yanıtlar büyük olasılıkla C++ örtük dönüşümler için referans noktası haline geleceğinden, şablon argümanları için bunu eklemek istiyorum, kurallar farklıdır.

Şablon bağımsız değişkeni için kullanılan bağımsız değişkenler için hiçbir dolaylı dönüşüme izin verilmez. Bu oldukça açık görünebilir, ancak yine de ince tuhaflığa yol açabilir.

Tipik bir örnek, std :: string ekleme operatörleri

std::string s; 
s += 67; // (1) 
s = s + 67; // (2) 

(1) derler ve iyi çalışır, operator+= üye fonksiyonudur, şablon karakter parametresi zaten char s arasında std::string (başlatmasını hacmileriyle). Bu nedenle, örtük dönüşümlere izin verilir (int ->char), s.ASCII bu operator+ serbest fonksiyonu ve burada kesinti kullanılan şablon karakter argüman olarak bildirilmiş olması

(2) bir derleyici hata veriyor 'C' olacaktı.