2016-06-24 26 views
1

Ich habe diesen Code:enable_shared_from_this wird nicht initialisiert, während shared_ptr von unique_ptr zur Basisklasse verwendet wird. Warum?

#include <iostream> 
#include <memory> 
#include <string> 

class base { 
public: 
    virtual void method() = 0; 
    virtual ~base() = default; 
}; 

class test: public base, public std::enable_shared_from_this<test> { 
private: 
    std::string text; 
public: 
    test(std::string text): text(std::move(text)) {} 
    ~test() = default; 
    virtual void method() override { 
    std::cout << "text: " << text; 
    std::cout << " this: " << this->shared_from_this().get() << std::endl; 
    } 
    static std::unique_ptr<base> create(std::string text) { 
    return std::unique_ptr<base>(new test(std::move(text))); 
    } 
}; 

static auto create_test(std::string text) { 
    return test::create(std::move(text)); 
} 

int main(int argc, char* argv[]) { 
    std::shared_ptr<base> shared = create_test("some text"); 
    shared->method(); 
    return 0; 
} 

Als ich dieses Programm ausführen ich Ausnahme "bad_weak_ptr". Können Sie erklären, warum "enable_shared_from_this" nicht initialisiert wurde?

Wenn ich Instanzen von zu unique_ptr<test> ändern, funktioniert es.

$ ./test 
terminate called after throwing an instance of 'std::bad_weak_ptr' 
    what(): bad_weak_ptr 
text: some textAborted (core dumped) 
+0

Obwohl ich bereits früher gesagt habe, dass Factory-Funktionen einen 'unique_ptr' zurückgeben sollen, ist es erforderlich, dass der Zeiger zum Zeitpunkt der Rückkehr vom Werk nicht bereits freigegeben ist. Wenn Ihre Klasse "shared_from_this" erbt, gibt es bereits zwei Zeiger, wenn die Factory zurückkehrt. In der Tat, [ich nannte diesen Fall explizit in meinem ursprünglichen Kommentar] (https://stackoverflow.com/questions/35953783/c11-make-shared-instancing#comment59565062_35953783) Also kontaktiere den, der dir empfohlen hat, 'unique_ptr' und' shared_from_this zusammen und sagen Sie ihnen, dass es eine Ausnahme gibt. –

Antwort

1

Was haben Sie sonst noch erwartet? Sie verwenden shared_ptr<base>. Die Basis wird nicht von enable_shared_from_this vererdet, so dass der gemeinsame Zeiger die schwache Referenz, die von shared_from_this verwendet wird, nicht initialisieren kann.

Funktioniert genau wie entworfen.

0

Sie können einen freigegebenen Zeiger aus einem test einem zu base mit dieser create Funktion gebaut Stimmen:

static std::shared_ptr<base> create(std::string text) { 
    return std::shared_ptr<test>(new test(std::move(text))); 
} 

Andernfalls wird es nicht funktionieren.
enable_shared_from_this funktioniert wie erwartet, aber bedenken Sie this:

std :: enable_shared_from_this ermöglicht ein Objekt t, die derzeit von einem std :: shared_ptr namens pt, um sicher zu generieren zusätzliche std :: shared_ptr Instanzen pt1 verwaltet wird, pt2, ... dass alle Aktienbesitz von t mit pt.

In Ihrem Code, erstellen Sie keine shared_pointer aus einem test.
Die obige Funktion create erledigt die Arbeit.