2014-05-15 39 views
9

Tôi đang sử dụng VS Express 2013 cố gắng biên dịch một dự án C++. Tôi đã tạo một lớp mẫu với một số hàm. Lớp và các hàm của nó đều nằm trong một tệp tiêu đề. Tôi đã bao gồm các tập tin, tôi đã sử dụng các lớp học, tôi đã gọi là chức năng từ nó, và mặc dù tất cả những visual studio sẽ không biên dịch các chức năng của lớp mà tôi không sử dụng. Tôi đã tắt tất cả các tối ưu hóa. Tôi có phải sử dụng một chức năng mà tôi đã viết chỉ để thấy rằng nó biên dịch hay không?Tại sao một số chức năng trong lớp mẫu của tôi không được biên dịch?

Dưới đây là các chức năng:

void remove(ID id) 
{ 
    sdfgsdfg456456456456sfdsdf 
} 

Các chức năng không nên biên dịch. Và thực sự dự án sẽ không biên dịch nếu tôi sử dụng hàm này, nhưng nếu tôi không sử dụng hàm mà dự án sẽ biên dịch, ngay cả khi tôi sử dụng các hàm khác từ bên trong lớp này.

Có khắc phục sự cố này không? Điều tương tự sẽ xảy ra nếu tôi triển khai hàm trong tệp .cpp?

Chỉnh sửa: Tôi đã bỏ qua đề cập đến nó là một lớp mẫu. Tôi đã thêm thông tin đó vào.

+0

Bạn biên dịch trong cấu hình gỡ lỗi, hoặc trong phiên bản cấu hình? – dasblinkenlight

+0

Trong cấu hình phát hành. – user1594138

+0

Điều tương tự có xảy ra khi bạn biên dịch trong cấu hình gỡ lỗi không? – dasblinkenlight

Trả lời

11

Như được tiết lộ trong nhận xét, lý do điều này xảy ra là vì remove() là một chức năng trong mẫu lớp học. Trình biên dịch chỉ instantiates mã mẫu nếu nó thực sự được sử dụng; nếu bạn không gọi remove(), nó có thể có tất cả các lỗi cú pháp bạn muốn và không ai sẽ phàn nàn.

Nhiều chính thức, § 14.7.1 của các trạng thái tiêu chuẩn (tôi nhấn mạnh):

Các instantiation tiềm ẩn của một lớp mẫu chuyên môn gây instantiation ngầm của tờ khai, nhưng không phải là định nghĩa hoặc đối số mặc định, các hàm thành viên lớp

Và sau đó trong phần giống nhau:

An thực hiện sẽ không ngầm nhanh chóng một mẫu chức năng , một mẫu thành viên, một hàm thành viên phi ảo, một lớp học viên , hoặc một thành viên dữ liệu tĩnh của một lớp mẫu mà không đòi hỏi instantiation.

(từ "tiềm ẩn" là chìa khóa ở đây, nếu bạn sử dụng explicit template instantiation, trình biên dịch sẽ ngay lập tức cố gắng nhanh chóng tất cả các thành viên sử dụng loại chỉ định (s) và thất bại nếu bất kỳ không biên dịch)

Đây không chỉ là một tối ưu hóa; bạn có thể khai thác hành vi này để khởi tạo các mẫu lớp với các kiểu chỉ hỗ trợ một tập hợp con các hoạt động của khuôn mẫu. Ví dụ: giả sử bạn viết một lớp mẫu sẽ được sử dụng với các loại hỗ trợ thao tác bar() và ngoài ra, một số cũng sẽ hỗ trợ baz().Bạn có thể làm điều này:

template<typename T> 
class Foo 
{ 
private: 
    T _myT; 

public: 
    void bar() 
    { 
     _myT.bar(); 
    } 

    void baz() 
    { 
     _myT.baz(); 
    } 
}; 

Bây giờ giả sử bạn có những quá:

struct BarAndBaz 
{ 
    void bar() {} 
    void baz() {} 
}; 

struct BarOnly 
{ 
    void bar() {} 
}; 

này sẽ biên dịch và chạy tốt:

void f() 
{ 
    Foo<BarAndBaz> foo1; 
    foo1.bar(); 
    foo1.baz(); 

    Foo<BarOnly> foo2; 
    foo2.bar(); 
    // don't try foo2.baz()! 
    // or template class Foo<BarOnly>! 
} 
+2

Có thể đáng nói đến việc khởi tạo rõ ràng, tức là ngay lập tức sẽ cố gắng khởi tạo tất cả các chức năng của thành viên. Cú pháp là 'lớp mẫu Foo ;'. –

+0

@MooingDuck Điều đó có vẻ giống như một bổ sung đáng giá; đã chỉnh sửa – dlf

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