Pytanie Co się dzieje, gdy klasa i funkcja mają tę samą nazwę?


#include <iostream>
using namespace std;

struct test
{
    test(){cout<<"class"<<endl;}
};
void test(){cout<<"function"<<endl;}

int main()
{
    test();
    return 0;
}

Wydajność:

function  

(VS2013 ang gcc 4.8.1)

Dlaczego wybrano funkcję? Czy to nie dwuznaczność?


18
2017-10-13 14:06


pochodzenie


Myślę, że kompilator wybiera tę funkcję, ponieważ klasa nigdy nie jest wywoływana z jej podstawową nazwą. Jeśli usuniesz test void (), prawdopodobnie uzyskasz niezdefiniowaną funkcję ... to nie jest ambicja, ponieważ te dwie są zawsze wywoływane przez różne konteksty ... - Leonardo Bernardini
Sprawdź to pytanie, jest to podobne: stackoverflow.com/questions/7763802/... @LeonardoBernardini Nie otrzymasz niezdefiniowanej funkcji, jeśli usuniesz void test (), ponieważ wtedy kompilator utworzy nowy obiekt testowy, ale nie będzie go nigdzie przypisywać. - Cantfindname
możesz osiągnąć swoją klasę dzięki struct test t{}; składnia - Piotr Skotnicki


Odpowiedzi:


To się nazywa ukrywanie imienia i opisane w

3.3 Zakres [basic.scope]

3.3.1 Deklaratywne regiony i zakresy [basic.scope.declarative]

4) Biorąc pod uwagę zestaw deklaracji w jednym regionie deklaratywnym, każdy z nich   który określa tę samą niekwalifikowaną nazwę,
 - wszyscy odnoszą się do   ten sam podmiot lub wszystkie odnoszą się do funkcji i szablonów funkcji; lub   
- dokładnie jedna deklaracja powinna zawierać nazwę klasy lub wyliczenie   nazwa, która nie jest nazwą typedef, a pozostałe deklaracje będą wszystkie   odnoszą się do tej samej zmiennej lub modułu wyliczającego lub wszystkie odnoszą się do funkcji   i szablony funkcji; w tym przypadku nazwa klasy lub wyliczenie   imię jest ukryte (3.3.10). [...]

podkreśl moje.

Pamiętaj, że zmiana kolejności deklaracji nie ma wpływu na wynik:

void test(){cout<<"function"<<endl;}

struct test
{
    test(){cout<<"class"<<endl;}
};

int main()
{
    test();
    return 0;
}

nadal drukuje function.

W przypadku, gdy nie jest to oczywiste, nie rób tego :)


18
2017-10-13 14:15



Powinieneś chyba zauważyć, że jest to hack, ze względu na kompatybilność z C, i prawdopodobnie nie chcesz go używać w rzeczywistym kodzie. - James Kanze
@JamesKanze Nie wiedziałem tego. - Luchian Grigore
+1 dla "nie rób tego". - Ryan
Nie wiedziałeś, że jest to kompatybilność z C, lub nie wiedziałeś, że to zły pomysł :-). Prawdziwym powodem jest wsparcie funkcji Posix stat(który ma parametr out struct stat*); w C potrzebujesz structi nazwiska po struct są wyszukiwane w innej przestrzeni nazw niż pozostałe. Nieco kłopotliwe reguły w C ++ są próbą wspierania tego, a jednocześnie pozwalają na korzystanie z bibliotek C, takich jak Posix. (I jestem pewien, że zostało to udokumentowane w niektórych wczesnych specyfikacjach, może ARM.) - James Kanze
Musi być jakiś sposób na zhackowanie tego, żeby zrobić coś szalonego ... - Mehrdad


Od N3485 §3.3.10 [basic.scope.hiding] / 2:

Nazwa klasy (9.1) lub nazwa wyliczenia (7.2) może być ukryta pod nazwą zmiennej, członka danych,   funkcja lub moduł wyliczający zadeklarowany w tym samym zakresie.

Dlatego funkcja ma pierwszeństwo przed klasą.

Jak wspomniano w komentarze, klasa jest nadal dostępna przez class lub struct słowo kluczowe. Jeśli klasa miała pierwszeństwo, funkcja byłaby niedostępna.


9
2017-10-13 14:15





Nie jestem pewien, czy jedna z poprzednich odpowiedzi to "dlaczego" dla konkretnego przypadku.

Nie zrozum mnie źle; Są prawdziwe i dokładne.

Po prostu myślę, że to jest prostsze.

W twoim przykładzie nigdy nie tworzysz instancji struct.

Innymi słowy, zadeklarowałeś to, ale nigdy go nie używałeś.

Ponieważ nigdy nie odwoływałeś się do tego, nigdy nie jest wywoływany.

Priorytet nazwy i tak naprawdę nie ma tu zastosowania, ponieważ nigdy nie utworzono struktury.

Mam nadzieję że to pomoże,

-Jan


-3
2017-10-13 17:14



Powinieneś cytować dowolne źródło lub dokumentację, aby uzasadnić to, co myślisz, lub dostarczyć dowody, które potwierdzają to. W tej odpowiedzi nie udało Ci się tego zrobić. - Krzysztof Jabłoński
Ta odpowiedź nie jest nawet logiczna sama w sobie: klasa nigdy nie jest tworzona bo zasady pierwszeństwa cytowane w innych odpowiedziach wymagają wywoływania funkcji. Jeśli pierwszeństwo będzie obowiązywać w odwrotnym kierunku, zostanie utworzony tymczasowy obiekt i zostanie wywołany konstruktor. Mówiąc "precedencja i takie nie mają zastosowania, ponieważ struktura nie jest tworzona" jest po prostu błędna. - Oguk