2009-05-29 14 views
16

Jestem początkującym w C++, więc przepraszam, jeśli pytanie jest zbyt proste.C++ pusty konstruktor String

Próbowałem zebrać struny konstrctury i wypróbować je wszystkie (aby je zapamiętać).

string strA();   // string(); empty string // incorrect 
string strB("Hello"); // string(const char* str) 
string strC("Hello",3); // string(const char* str, size_type length) 
string strD(2,'c');  // string(size_type lenght, const char &c) 
string strE(strB);  // string(const string& s) 

cout << strA << endl; 
cout << strB << endl; 
cout << strC << endl; 
cout << strD << endl; 
cout << strE << endl; 

Wszystkie z nich pracuje za wyjątkiem Stra. Wyświetla "1". Dlaczego? Jaki jest w tym przypadku typ strA? Jak mogę sprawdzić typ rzeczy, gdy jestem pewien?

Zauważyłem, że poprawny sposób jest to (co swoją drogą wydaje się być niespójne z innymi konstruktorami, czasami parens czasami nie ma nawiasy):

string strA; 

PS: pytanie pogrubione, zwykle bez znaczenia odpowiedzi zostaną odrzucone.

Odpowiedz

32

To bardzo popularne hasło. Gramatyka C++ jest niejednoznaczna. Jedną z zasad rozwiązywania niejednoznaczności jest "jeśli coś wygląda na deklarację, jest deklaracją". W tym przypadku zamiast definiowania zmiennej zadeklarowałeś prototyp funkcji.

string strA(); 

jest równoważna

string strA(void); 

prototyp funkcji nie-Arg, która zwraca ciąg znaków.

Jeśli chcesz jawnie wywołać konstruktor no-Arg spróbuj tego:

string strA=string(); 

To nie jest w pełni równoważne - to znaczy „stworzyć tymczasowy ciąg przy użyciu nie-Arg konstruktora, a następnie skopiować go zainicjować zmienną strA ', ale kompilator może go zoptymalizować i pominąć kopiowanie.

Edycja: Here is an appropriate item in C++ FAQ Lite

+3

I to jest jeden z powodów, dla których przestałem używać C++. –

+3

@Dietrich Epp: To też mi przeszkadzało. Domyślam się, że jest to cena zapłacona za utrzymanie zgodności z C. Alternatywą jest użycie C, który ma metryczny ton problemów, domyślam się, że lepiej jest zachować C++ i uniknąć tej pułapki. – paercebal

+0

, jak o 'std :: string strA (" ");' – CaptainDaVinci

13

Uważa

string strA(); 

jako deklaracja funkcji.

Dla domyślnej użycia konstruktora:

string strA; 
+2

Możesz używać tej notacji podczas przydzielania sterty: string * strA = new string(); – Skilldrick

6

W C++, jak w C, nie jest to reguła, która mówi, że coś, co wygląda jak declarartion będą traktowane jako deklaracja.

string strA(); 

wygląda jak deklaracja funkcji, więc jest traktowana jako jedna. Potrzebne są:

string strA; 
1

Kompilator interpretuje string strA() jako prototyp funkcji z funkcją która odbywa void argumenty i zwraca obiekt typu string. Jeśli chcesz utworzyć pusty obiekt typu string, użyj string strA; (bez paranthes).

3

Drukuje 1 ponieważ wskaźniki do funkcji zawsze przekształca się numeryczny true.

+5

Tylko jeśli wskaźnik do funkcji ma wartość inną niż null. W każdym razie wskaźnik do funkcji powinien wskazywać na jego definicję, a tego tutaj brakuje. To nie powinno być połączone. – MSalters

2

tkopec ma rację, dlaczego nie działa. Aby odpowiedzieć na drugie pytanie, oto jak sprawdzić typ:

template<typename TEST> void Error_() { 
    TEST* MakeError = 1; 
} 

Dzwoniąc Error_(StrA); otrzymasz błąd kompilacji, a kompilator będzie prawdopodobnie powiedzieć, że stało się to w Error_< std::basic_string<char, std::allocator<char> > (*)(void)>(std::basic_string<char, std::allocator<char> > (*)(void)) Teraz std :: basic_string> jest po prostu std :: string, więc to naprawdę oznacza Error_< std::string (*)(void)> (std::string (*)(void)). Część między "<>" powtarza się pomiędzy "()", i jest to sype strA. W tym przypadku, std::string (*)(void).

+0

Typ strA jest funkcją. std :: string (void). To nie wskaźnik funkcji. Musiałby zadeklarować go jako ciąg (* strA)(); jeśli chciał, żeby był wskaźnikiem funkcji.Prawdopodobnie wiem, co miałeś na myśli, ale twoje ostatnie zdania brzmią jak mówisz, że to wskaźnik funkcji. –

4

Nie sądzę, że w tym przypadku obowiązuje zasada "jeśli może to być deklaracja, która została uznana za deklarację". Ponieważ w dalszej części oba rzeczy są deklaracje

string a; 
string a(); 

Jedno jest deklaracja obiektu, a druga jest deklaracja funkcji. Zasada ma zastosowanie w innych przypadkach. Na przykład, w tym przypadku:

string a(string()); 

W takim przypadku string() może oznaczać dwie rzeczy.

  • Deklaracja nienazwanego parametru funkcji
  • Expression tworząc domyślny skonstruowane string

Fule stosuje tutaj, a string() należy rozumieć tak samo jak poniżej, nazwany parametr (nazwy nie mają znaczenia w parametrach podczas deklarowania funkcji)

string a(string im_not_relevant()); 

Jeśli funkcja przyjmuje jako parametr tablicę lub anot jej funkcja, parametr rozpada się na wskaźnik. W przypadku parametru funkcji, do wskaźnika do funkcji. Tak więc, jest to równoznaczne z następujących produktów, które mogą wyglądać bardziej zaznajomieni

string a(string (*im_not_relevant)()); 

Ale w twoim przypadku, to raczej składnia, że ​​robi się na drodze. Mówi się, że poniższe jest deklaracja funkcji. Nigdy nie może być deklaracja obiektu (mimo że prawdopodobnie zamierzonego przez programistę!)

string a(); 

Więc nie ma wątpliwości w związku z tym w pierwszej kolejności, a więc deklaruje funkcję. Ponieważ string ma zdefiniowany przez użytkownika konstruktor, można po prostu pominąć nawiasy, a efekt pozostaje taki sam, jak zamierzano.

Powiązane problemy