2014-12-06 16 views
10

sagen, ich habe zwei Klassen:unique_ptr und Forward-Deklaration

"foo.h"

#pragma once  
class Foo 
{ 
public: 
    Foo() 
    { 

    }; 

    ~Foo() 
    { 

    }; 
}; 

"A. h"

#pragma once 
#include <memory> 

class Foo; 

class A 
{ 
public: 
    A(){}; 
    ~A(){}; 

    std::unique_ptr<Foo> foo; 
}; 

A hält ein unique_ptr von Foo. Ich wollte Foo in "A.h" nicht einschließen, also habe ich es vorwärts erklärt. Mit nur uns darauf, die Klasse zu erklären Foo in „Ah“, erhalte ich eine Kompilierung Fehler:

error C2027: use of undefined type 'Foo' 
error C2338: can't delete an incomplete type 

So wurde nach I this Artikel darüber, wie diese Fehler zu vermeiden und bewegt destructor A ist in einem eigenen CPP-Datei, wo ich auch sind Foo:

"A.cpp"

#include "A.h" 

#include "Foo.h" 

A::A() 
{ 

} 

A::~A() 
{ 

} 

nach dem destructor von A in "A.cpp" Umsetzung, ich bin in der Lage, das Programm zu kompilieren, weil die Klasse Foo in bekannt ist " A.cpp ". Dies erscheint logisch, da unique_ptr den vollständigen Typ benötigt, um den Destruktor aufzurufen. Aber zu meiner Überraschung, nachdem ich den Konstruktor von A (in "A.h" sowie "A.cpp") kommentiert habe, bekomme ich den gleichen Fehler. Wie ist das möglich? Warum beschwert sich der Compiler darüber, nicht in der Lage zu sein, Foo's Destruktor aufzurufen, wenn A keinen Konstruktor hat?

EDIT: Ich habe die 4 Dateien hochgeladen, damit Sie das Programm testen können. Ich bin mit MSVC++ von Visual Studio 2013.

http://www.filedropper.com/test_61

+5

'A' hat einen Konstruktor haben, wenn Sie Ihren Constructo Kommentar aus r: Ein Standardkonstruktor wird vom Compiler bereitgestellt, und dieser Konstruktor erhält eine Inline-Definition. – dyp

+0

Ja, aber mit dem Standardkonstruktor bekomme ich den Compilerfehler, dass er einen kompletten Typ nicht löschen kann. Wenn ich meinen eigenen leeren Konstruktor schreibe, der genauso aussehen sollte wie der Standardkonstruktor, bekomme ich diese Compilerfehler nicht. – abcheudg234

+0

Zeigen Sie uns den Code, der nicht funktioniert? –

Antwort

-1

Es ist nicht möglich, 'A' auf keinen Konstruktor haben.

Wenn Sie den Konstruktor Sie schrieb einen Kommentar, wird der Compiler einen Standardkonstruktor für Sie und es wird nicht unbedingt an der gleichen Stelle sein Sie die eine definierte Sie gemacht. Dieses Problem verursacht.

+1

Aber warum muss ich den Konstruktor in A.cpp überhaupt definieren? Ich verstehe, dass der Compiler beschwert, dass der Destruktor von A irgendwo definiert werden muss, wo Foo.h enthalten ist - so dass es ein vollständiger Typ ist und der Destruktor von A tatsächlich Foo zerstören kann. Aber ich verstehe nicht, warum A's CONstructor auch in A.cpp definiert werden muss. Sie können den Code ausprobieren, indem Sie die Klassen kopieren und A in main() instanziieren. Beim Auskommentieren von A's Konstruktor wird der Code nicht kompiliert. – abcheudg234

+3

Um welchen Compiler klagen Sie? –

+1

Ich verwende den MSVC++ - Compiler von Visual Studio 2013. – abcheudg234

14

Der Konstruktor benötigt Zugriff auf das deleter in genau der gleichen Art und Weise die destructor tut: Ausnahme Sicherheit erfordert, dass der Konstruktor der Lage sein, Roll-Back Initialisierung aller Mitglieder in dem Fall, dass Körper Konstruktor Würfe:

[C++14: 12.6.2/10]: In a non-delegating constructor, the destructor for each potentially constructed subobject of class type is potentially invoked (12.4). [ Note: This provision ensures that destructors can be called for fully-constructed sub-objects in case an exception is thrown (15.2). —end note ]

Verwandte: