C işlev bildiricileri
Her şeyden önce, C vardır. C'de A a()
fonksiyon beyanıdır. Örneğin putchar
, aşağıdaki bildirime sahiptir. Normalde, bu tür bildirimler başlık dosyalarında saklanır, ancak işlev bildiriminin nasıl göründüğünü biliyorsanız, hiçbir şey bunları elle yazmanızı engellemez. Bağımsız değişken adları bildirimlerde isteğe bağlıdır, bu nedenle bu örnekte atladım.
int putchar(int);
Bu, kodu böyle yazmanıza olanak tanır.
int puts(const char *);
int main() {
puts("Hello, world!");
}
C ayrıca işlevleri işlev çağrısı gibi görünen güzel okunabilir sözdizimiyle işlevleri bağımsız değişken olarak tanımlayan işlevleri tanımlamanıza olanak tanır (bir işaretçiyi işlevine döndürmeyeceğiniz sürece okunabilir).
#include <stdio.h>
int eighty_four() {
return 84;
}
int output_result(int callback()) {
printf("Returned: %d\n", callback());
return 0;
}
int main() {
return output_result(eighty_four);
}
Bahsettiğim gibi C, başlık dosyalarında argüman adlarının çıkarılmasına izin verir, bu nedenle output_result
başlık dosyasında şöyle görünür.
int output_result(int());
Yapıcıda bir argüman
Bunu tanımıyor musun? Size hatırlatmama izin verin.
A a(B());
Evet, tam olarak aynı işlev beyanı. A
olduğunu int
, a
olduğunu output_result
ve B
olduğunu int
.
C ++ 'nın yeni özellikleriyle C çatışmasını kolayca fark edebilirsiniz. Tam olarak söylemek gerekirse, yapıcılar sınıf adı ve parantez olup, ()
yerine alternatif bildirim sözdizimidir =
. Tasarım gereği, C ++ C koduyla uyumlu olmaya çalışır ve bu nedenle bu durumla uğraşmak zorundadır - pratikte kimse umurunda olmasa bile. Bu nedenle, eski C özelliklerinin yeni C ++ özelliklerine göre önceliği vardır. Bildirimlerin dilbilgisi, ()
başarısız olursa yeni sözdizimine dönmeden önce adı işlev olarak eşleştirmeye çalışır .
Bu özelliklerden biri mevcut değilse veya farklı bir sözdizimine sahip olsaydı ( {}
C ++ 11'deki gibi), bu sorun hiçbir zaman tek bir argümanla sözdizimi için olmazdı.
Şimdi neden A a((B()))
işe yaradığını sorabilirsiniz . output_result
Yararsız parantezler ile açıklayalım .
int output_result((int()));
Çalışmaz. Dilbilgisi, değişkenin parantez içinde olmamasını gerektirir.
<stdin>:1:19: error: expected declaration specifiers or ‘...’ before ‘(’ token
Ancak, C ++ burada standart ifade bekliyor. C ++ ile, aşağıdaki kodu yazabilirsiniz.
int value = int();
Ve aşağıdaki kod.
int value = ((((int()))));
C ++, parantez içindeki ifadenin, C türünün aksine, ... iyi ... ifadesi olmasını bekler. Parantez burada bir şey ifade etmiyor. Bununla birlikte, işe yaramaz parantezler eklenerek, C işlevi bildirimi eşleştirilmez ve yeni sözdizimi düzgün şekilde eşleştirilebilir (bu, yalnızca bir ifade bekler 2 + 2
).
Yapıcıdaki diğer argümanlar
Elbette bir argüman güzel, ama ikisine ne olacak? Yapıcıların sadece bir argümanı olabilir. İki argüman alan yerleşik sınıflardan biristd::string
std::string hundred_dots(100, '.');
Bu iyi ve güzel (teknik olarak, eğer yazılırsa en sinir bozucu ayrıştırma olurdu std::string wat(int(), char())
, ama dürüst olalım - bunu kim yazacak? Ama diyelim ki bu kodun can sıkıcı bir sorunu var. parantez içindeki her şey.
std::string hundred_dots((100, '.'));
Pek değil.
<stdin>:2:36: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
In file included from /usr/include/c++/4.8/string:53:0,
from <stdin>:1:
/usr/include/c++/4.8/bits/basic_string.tcc:212:5: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
basic_string<_CharT, _Traits, _Alloc>::
^
G ++ çalışır dönüştürmek için neden emin değilim char
için const char *
. Her iki durumda da, yapıcı yalnızca bir tür değerle çağrıldı char
. Bir tür argümanı olan aşırı yük yoktur char
, bu nedenle derleyici karıştırılır. Siz sorabilirsiniz - neden argüman char türünde?
(100, '.')
Evet, ,
işte virgül operatörü. Virgül operatörü iki argüman alır ve sağ taraf argümanını verir. Gerçekten kullanışlı değil, ama açıklamam için bilinmesi gereken bir şey.
Bunun yerine, en sinir bozucu ayrışmayı çözmek için aşağıdaki kod gereklidir.
std::string hundred_dots((100), ('.'));
Argümanlar parantez içinde, ifadenin tamamı değil. Aslında, C ++ özelliğini kullanmak için C dilbilgisinden biraz kopmak yeterli olduğundan, ifadelerden sadece birinin parantez içinde olması gerekir. İşler bizi sıfır argüman noktasına getiriyor.
Yapıcıdaki sıfır argümanlar
eighty_four
Açıklamamdaki işlevi fark etmiş olabilirsiniz .
int eighty_four();
Evet, bu aynı zamanda en sinir bozucu ayrışmadan da etkilenir. Bu geçerli bir tanımdır ve başlık dosyaları oluşturduysanız büyük olasılıkla görmüşsünüzdür (ve yapmanız gerekir). Parantez eklemek sorunu çözmez.
int eighty_four(());
Neden böyle? Şey, ()
bir ifade değildir. C ++ ile, parantezler arasına bir ifade koymanız gerekir. auto value = ()
C ++ ile yazamazsınız , çünkü ()
hiçbir şey ifade etmez (ve boş demet gibi (Python'a bakın), sıfır değil tek bir argüman olurdu). Pratik olarak bu, C ++ 11 sözdizimini kullanmadan steno sözdizimini kullanamayacağınız anlamına gelir {}
, çünkü parantez içine alınacak ifade yoktur ve işlev bildirimleri için C dilbilgisi her zaman uygulanır.
(B())
sadece bir C ++ ifadesi, başka bir şey değil. Herhangi bir istisna değildir. Yaptığı tek fark, büyük olasılıkla bir tür olarak ayrıştırılamamasının hiçbir yolu olmamasıdır ve bu yüzden değildir.