2012-04-18 36 views
10

Có phải O.K. thế nào để xác định chức năng ảo của lớp mẫu bên ngoài cơ thể của nó? Chức năng ảo không thể được gạch chân, nhưng để tránh nhiều định nghĩa trong các đơn vị biên dịch, chúng sẽ được đánh dấu inline (giả định rằng các tiêu đề mẫu sẽ được bao gồm trong nhiều tệp nguồn). Mặt khác, trình biên dịch tự do bỏ qua inline, vì vậy điều này có vẻ hợp lệ. Ví dụ: mã bên dưới chính xác:Định nghĩa mẫu bên ngoài lớp cơ thể

template <typename T> 
class C 
{ 
public: 
    virtual void f(T val); 
}; 

template <typename T> 
inline 
void C<T>::f(T val) 
{ 
    //definition 
} 

?

BTW gcc (3.4.2) cho phép bỏ qua inline trước định nghĩa hàm f(T val) nhưng không được trước chức năng tương tự của lớp thông thường. Nó chỉ là hành vi của gcc?

+5

Bạn sử dụng gcc * 3.4.2 *? – jpalecek

+0

@jpalecek trong ví dụ cụ thể này, vâng. – doc

+1

@doc - Chức năng ảo * có thể * được khai báo 'nội tuyến' (nhưng không cần thiết ở đây). Trình biên dịch chỉ có một chút khó khăn hơn để tìm ra chính xác khi nào các hàm có thể được inlined. –

Trả lời

10

Có, đó là OK ngay cả khi không inline Nó hoạt động tương tự cho hàm thành viên bình thường và biến tĩnh:

// everything in the header: 
template <class T> 
class A 
{ 
    static int i; 
}; 

template <class T> 
int A<T>::i=0; 

quote Tiêu chuẩn: (3,2/5)

có thể có mor e hơn một định nghĩa của một loại lớp (Điều 9), kiểu liệt kê (7.2), hàm nội tuyến với liên kết ngoài (7.1.2), mẫu lớp (Điều 14), mẫu chức năng không tĩnh (14.5.6), tĩnh thành viên dữ liệu của mẫu lớp (14.5.1.3), chức năng thành viên của mẫu lớp (14.5.1.1) hoặc chuyên môn mẫu cho mà một số tham số mẫu không được chỉ định (14.7, 14.5.5) trong chương trình được cung cấp rằng mỗi sự xác định xuất hiện trong một đơn vị dịch thuật khác, và cung cấp các định nghĩa thỏa mãn các yêu cầu sau ...

Các yêu cầu về cơ bản là hai định nghĩa phải giống hệt nhau.

Nó không hoạt động trong trường hợp các lớp thông thường. Phải có tối đa một định nghĩa trong toàn bộ chương trình.

+0

Tại sao một người nào đó đã bỏ phiếu cho câu trả lời này:? – doc

3

Bạn có thể xác định các hàm ở đó, miễn là bất kỳ mã nào cần khởi tạo hàm đang được đề cập đều có khả năng hiển thị mã đó tại thời gian biên dịch (không phải thời gian liên kết).

Việc chia tách mẫu thành 2 tệp là một tiêu đề truyền thống, một là tiêu đề truyền thống và thứ hai là việc triển khai thực hiện, như với các chức năng không có khuôn mẫu và triển khai của chúng. Điểm khác biệt duy nhất là bạn cần # bao gồm tệp triển khai mẫu cũng như tiêu đề khi bạn muốn sử dụng nó.

4

Bạn có thể xác định phương thức mẫu bên ngoài định nghĩa class, trong cùng một tiêu đề, không sử dụng inline và không nhận được nhiều lỗi định nghĩa.

Đó là vì chức năng mẫu không tự tạo ra định nghĩa, nếu nó không hoàn toàn chuyên ngành. Để chứng minh quan điểm của tôi, những điều sau đây:

void C<int>::f(int) 
{ 
} 

sẽ dẫn đến lỗi liên kết, vì hàm này có định nghĩa trong trường hợp này. (Với điều kiện bạn bao gồm này trong nhiều đơn vị dịch Nếu bạn đánh dấu nó inline:...

inline void C<int>::f(int) 
{ 
} 

lỗi không còn xảy ra

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