2014-12-06 15 views
10

Nói rằng tôi có hai lớp:Unique_ptr và tờ khai chuyển tiếp

"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; 
}; 

Một nắm giữ một unique_ptr của Foo. Tôi không muốn bao gồm Foo trong "A.h", vì vậy tôi chuyển tiếp tuyên bố nó. Bởi chỉ cần chờ tuyên bố lớp Foo trong "Ah", tôi nhận được một lỗi thời gian biên dịch:

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

Vì vậy, tôi đã được sau this bài viết về cách tránh lỗi này và di chuyển của một destructor trong đó của tập tin cpp riêng nơi tôi cũng bao gồm Foo:

"A.cpp"

#include "A.h" 

#include "Foo.h" 

A::A() 
{ 

} 

A::~A() 
{ 

} 

Sau khi thực hiện các destructor của A trong "A.cpp", tôi có thể biên dịch chương trình, bởi vì lớp Foo được biết đến trong " A.cpp ". Điều này có vẻ hợp lý, bởi vì unique_ptr cần kiểu hoàn chỉnh để gọi nó là destructor. Nhưng với sự ngạc nhiên của tôi, sau khi bình luận ra các nhà xây dựng của A (trong "A.h" cũng như "A.cpp"), tôi nhận được cùng một lỗi. Sao có thể như thế được? Tại sao trình biên dịch phàn nàn về việc ong không thể gọi hàm hủy của Foo khi A không có hàm tạo?

EDIT: Tôi đã tải lên 4 tệp để bạn có thể kiểm tra chương trình. Tôi đang sử dụng MSVC++ của Visual Studio 2013.

http://www.filedropper.com/test_61

+5

'A' không có một constructor khi bạn nhận xét ra constructo của bạn r: một hàm tạo mặc định được trình biên dịch cung cấp, và hàm tạo này nhận định nghĩa nội tuyến. – dyp

+0

Có, nhưng với hàm tạo tiêu chuẩn, tôi nhận được lỗi trình biên dịch mà anh ta không thể xóa một loại hoàn chỉnh. Khi viết constructor rỗng của riêng tôi, nó sẽ trông giống như hàm mặc định, tôi không nhận được các lỗi trình biên dịch này. – abcheudg234

+0

Hiển thị cho chúng tôi mã không hoạt động? –

Trả lời

-1

Nó không thể cho 'A' để không có một constructor.

Nếu bạn nhận xét hàm tạo mà bạn đã viết, trình biên dịch sẽ tạo một hàm tạo mặc định cho bạn và nó sẽ không nhất thiết ở cùng vị trí bạn đã xác định. Gây ra vấn đề.

+1

Nhưng tại sao tôi phải xác định hàm tạo trong A.cpp? Tôi hiểu rằng trình biên dịch phàn nàn rằng một destructor của A đã được định nghĩa ở đâu đó mà Foo.h được bao gồm - để nó là một loại hoàn chỉnh và một destructor của A thực sự có thể phá hủy Foo. Nhưng tôi không hiểu tại sao A's CONstructor cũng phải được định nghĩa trong A.cpp. Bạn có thể thử mã bằng cách sao chép các lớp và khởi tạo A trong main(). Khi bình luận ra constructor của A, mã sẽ không biên dịch. – abcheudg234

+3

Trình biên dịch nào bạn đang kiện? –

+1

Tôi đang sử dụng trình biên dịch MSVC++ của Visual Studio 2013. – abcheudg234

14

Các nhà xây dựng cần truy cập vào các deleter chỉ trong cùng một cách destructor làm: an toàn ngoại lệ đòi hỏi rằng các nhà xây dựng có thể cuộn lại khởi động của tất cả các thành viên trong trường hợp đó cơ thể của constructor của bạn ném:

[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 ]

liên quan:

Các vấn đề liên quan