2010-10-25 37 views
11

Tôi đang gặp một số sự cố khi xác định một số tình trạng quá tải của nhà điều hành đối với các lớp mẫu. Ví dụ, hãy lấy lớp giả thuyết này.Quá tải toán tử trên các mẫu lớp

template <class T> 
class MyClass { 
    // ... 
}; 
  • điều hành + =

    // In MyClass.h 
    MyClass<T>& operator+=(const MyClass<T>& classObj); 
    
    
    // In MyClass.cpp 
    template <class T> 
    MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) { 
        // ... 
        return *this; 
    } 
    

    Kết quả do lỗi biên dịch này:

    no match for 'operator+=' in 'classObj2 += classObj1' 
    
  • hành < <

    // In MyClass.h 
    friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj); 
    
    
    // In MyClass.cpp 
    template <class T> 
    std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj) { 
        // ... 
        return out; 
    } 
    

    Kết quả trong cảnh báo trình biên dịch này:

    friend declaration 'std::ostream& operator<<(std::ostream&, const MyClass<T>&)' declares a non-template function 
    

Tôi đang làm gì sai ở đây?

+0

bạn có thể đăng một số mã thực mà không biên dịch? – Naveen

+0

@Naveen: bạn có thể nhận phiên bản được nén tại http://www.box.net/shared/v23rj2f8e7 – Pieter

Trả lời

7
// In MyClass.h 
MyClass<T>& operator+=(const MyClass<T>& classObj); 


// In MyClass.cpp 
template <class T> 
MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) { 
    // ... 
    return *this; 
} 

này không hợp lệ cho các mẫu. Mã nguồn đầy đủ của toán tử phải nằm trong tất cả các đơn vị dịch mà nó được sử dụng. Điều này thường có nghĩa là mã nằm trong tiêu đề.

Chỉnh sửa: Về mặt kỹ thuật, theo tiêu chuẩn, có thể xuất mẫu, tuy nhiên rất ít trình biên dịch hỗ trợ nó. Ngoài ra, bạn cũng có thể thực hiện ở trên nếu mẫu được khởi tạo rõ ràng trong MyClass.cpp cho tất cả các loại T- nhưng trên thực tế, thường sẽ làm mất đi điểm của mẫu.

Chỉnh sửa khác: Tôi đọc qua mã của bạn và cần một số công việc, ví dụ như toán tử quá tải []. Ngoài ra, thông thường, tôi sẽ làm cho kích thước một phần của các tham số mẫu, cho phép lỗi + hoặc + = bị bắt tại thời gian biên dịch và cho phép loại được phân bổ một cách có ý nghĩa. Lớp ngoại lệ của bạn cũng cần phải lấy được từ std :: exception. Tuy nhiên, không ai trong số những người liên quan đến lỗi biên dịch thời gian, họ không chỉ là mã tuyệt vời.

0

Bạn phải xác định rằng bạn là một mẫu chức năng:

MyClass<T>& operator+=<>(const MyClass<T>& classObj); 

Xem this C++ FAQ Lite câu trả lời để biết chi tiết.

12

Bạn cần phải nói như sau (kể từ khi bạn kết bạn với một tổng thể mẫu thay vì chỉ là một chuyên môn hóa của nó, trong trường hợp này bạn sẽ chỉ cần thêm một <> sau operator<<):

template<typename T> 
friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj); 

Trên thực tế, không cần khai báo nó như một người bạn trừ khi nó truy cập các thành viên riêng tư hoặc được bảo vệ. Vì bạn chỉ nhận được cảnh báo , có vẻ như tuyên bố tình bạn của bạn không phải là một ý tưởng hay. Nếu bạn chỉ muốn khai báo một chuyên môn đơn của nó như một người bạn, bạn có thể làm điều đó như được hiển thị bên dưới, với tuyên bố trước của mẫu trước lớp học của bạn, để operator<< được nhận dạng dưới dạng mẫu.

// before class definition ... 
template <class T> 
class MyClass; 

// note that this "T" is unrelated to the T of MyClass ! 
template<typename T> 
std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj); 

// in class definition ... 
friend std::ostream& operator<< <>(std::ostream& out, const MyClass<T>& classObj); 

Cả trên và theo cách này tuyên bố các chuyên ngành về nó như bạn bè, nhưng là người đầu tiên tuyên bố tất cả chuyên ngành như những người bạn, trong khi chỉ đứng thứ hai tuyên bố chuyên môn của operator<< như một người bạn mà T bằng với T của lớp cấp tình bạn.

Và trong trường hợp khác, tuyên bố của bạn có vẻ OK, nhưng lưu ý rằng bạn không thể += một MyClass<T> đến một MyClass<U> khi TU là loại khác nhau với lời tuyên bố đó (trừ khi bạn có một chuyển đổi ngầm giữa các loại). Bạn có thể làm cho bạn += thành viên mẫu

// In MyClass.h 
template<typename U> 
MyClass<T>& operator+=(const MyClass<U>& classObj); 


// In MyClass.cpp 
template <class T> template<typename U> 
MyClass<T>& MyClass<T>::operator+=(const MyClass<U>& classObj) { 
    // ... 
    return *this; 
} 
2

http://www.parashift.com/c++-faq-lite/template-friends.html

Điều này đã giúp tôi với cùng một vấn đề.

soln:

  1. Chuyển tiếp khai báo hàm bạn bè trước khi định nghĩa của lớp đó. Đối với ví dụ:

    template<typename T> class MyClass; // pre-declare the template class itself 
        template<typename T> std::ostream& operator<< (std::ostream& o, const MyClass <T>& x); 
    
  2. Khai báo các hàm bạn bè của bạn trong lớp của bạn với "<>" nối vào tên hàm.

    friend std::ostream& operator<< <> (std::ostream& o, const Foo<T>& x); 
    
+0

Liên kết dẫn đến thời gian chờ. – TobiMcNamobi

-1

Bằng cách này hoạt động:

class A 
{ 
    struct Wrap 
    { 
     A& a; 
     Wrap(A& aa) aa(a) {} 
     operator int() { return a.value; } 
     operator std::string() { stringstream ss; ss << a.value; return ss.str(); } 
    } 
    Wrap operator*() { return Wrap(*this); } 
}; 
Các vấn đề liên quan