14

Forward declaration pozwala nam odłożyć definiowanie rzeczywistego typu do pliku implementacji. Jest to dozwolone w nagłówku dla wskaźników lub odniesień do zadeklarowanego typu forward.Czy mój typ zwrotu musi być zdefiniowany?

I have been told że:

Zwracanie wartości przez nie wymaga definicji typu. Zgłoszenie do przekazania jest wystarczające

Czy ktoś może potwierdzić lub odrzucić to z faktycznym cytatem ze standardu? Miałem wrażenie, że to nie jest legalne.

+8

Może być jasne, co myślisz nie jest legalne, dokładnie? Na przykład, faktyczna próbka kodu, którą uważasz za nielegalną? – Yakk

+1

Dotyczy to deklaracji funkcji, a nie definicji. I nie, to nie jest cytat ze standardu. – juanchopanza

+4

Być może powinienem był powiedzieć: "Zwracanie wartości nie wymaga definicji typu **, gdy deklarujesz funkcję **. Deklaracja przekazania jest wystarczająca." Definiując tę ​​funkcję i kiedy ją wywołujesz, potrzebujesz definicji. –

Odpowiedz

25

Powracanie według wartości nie wymaga definicji typu. Deklaracja przekazania jest wystarczająca

Zgłaszanie funkcji zwracającej wartość nie wymaga definicji typu. Dobrze utworzone demo:

struct S; 
S foo(); 
struct S {}; 
int main() { 
    foo(); 
} 
S foo() {} 

Definiowanie lub wywoływanie funkcji zwracającej wartość wymaga definicji typu. Standardowy projekt [basic.def.odr]:

5 Dokładnie definicja klasy jest wymagane w jednostce tłumaczeniowej jeśli klasa jest używana w sposób wymagający typ klasy jest kompletna. [Przykład: ... [wycinanie] ... [Uwaga: Reguły deklaracji i wyrażeń opisują, w jakich kontekstach wymagane są pełne typy klas. typu klasy T musi być kompletna, jeśli:

  • [ciach]
  • 5,9 funkcja z rodzaju powrotnego lub typu argumentu typu T określone ([basic.def]) albo jako ([wyrażenie .Połączenia]) lub
  • [ciach]

zgłoszenie funkcja o niepełnej typu powrotnym pośrednio pozostawiono mocy nie zostanie zakazane przez jedną z zasad w liście.

Zasadą jest ponownie sformułowane w dalszej części standard, i możliwe jest rozluźniony wyjątkiem [dcl.fct] (dzięki @cpplearner za wskazanie tego wykluczyć):

11 Rodzaje nie określa się powrót bądź typy parametrów. Typ parametru lub typ zwracany dla definicji funkcji nie może być niekompletnym (prawdopodobnie kwalifikowanym w Cv) typem klasy w kontekście definicji funkcji, chyba że funkcja zostanie usunięta ([dcl.fct.def.delete]).


Źle uformowane demo:

struct S; 
S foo(){} // oops 
struct S {}; 

Innym źle sformułowane demo:

struct S; 
S foo(); 
int main() { 
    foo(); // oops 
} 
struct S {}; 
S foo() {} 
+6

Wycofano, ponieważ wydaje się to być dokładnie potwierdzeniem standardu, którego szukał OP. –

+0

Dobrze. Jeśli myślisz o tym z perspektywy projektowania kompilatora, ma to sens: typ musi być kompletny, jeśli kompilator musi znać jego rozmiar/wyrównanie. Ma to znaczenie w generowaniu kodu dla wyrażeń, a także w ustawianiu struktury powrotu dla funkcji. Ale oczywiście nie mają znaczenia dla deklaracji forward, która nie pojawia się w wygenerowanym kodzie i aktualizuje tylko wewnętrzne struktury kompilatora. – wchargin