2010-11-16 31 views
6

Nếu tôi có một đặc điểm kỹ thuật lớp mẫu như vậy,Làm cách nào để tránh trùng lặp đặc tả mẫu lớp cho từng chức năng của thành viên?

template <typename T> 
class MyClass { 
public: 
    void fun1(); 
    // ... 
    void funN(); 
}; 

template <typename T> 
void MyClass<T>::fun1() { 
    // definition 
} 

// ... 

template <typename T> 
void MyClass<T>::funN() { 
    // definition 
} 

Nếu tôi thay đổi mẫu lớp để cái gì khác, nói rằng tôi thêm một tham số phụ:

template <typename T, typename U> 
class MyClass { 
    // ... 
}; 

Sau đó, tôi phải thay đổi mỗi chức năng định nghĩa (fun1, ..., funN) để đồng ý với đặc tả mẫu lớp học:

template <typename T, typename U> 
void MyClass<T,U>::fun1() { //... } 

Có chiến lược nào để tránh điều này không? Tôi có thể sử dụng macro hay không

#define DFLT_TEMPLATE template<typename T, typename U> 
#define DFLT_CLASS class<T,U> 

DFLT_TEMPLATE 
void DFLT_CLASS::fun1() { // ... } 

Hoặc đây có phải là hành vi không tốt?

+0

Không quan tâm về những gì người khác nói. Nếu bạn thực sự ghét ** viết lại nhiều thứ (như tôi) - thì chỉ cần sử dụng macro. Tôi nhận thức được tất cả những hạn chế và cạm bẫy của việc sử dụng macro. Tuy nhiên, tôi vẫn thích macro sao chép + dán và v.v. – valdo

+0

P.S. Từ kinh nghiệm cá nhân của tôi viết lại những thứ, ngoài việc mất tinh thần, nguy hiểm hơn nhiều so với sử dụng macro – valdo

+2

'Tìm & Thay thế 'giúp đây – Inverse

Trả lời

5

Đối với tôi , lợi ích của việc sử dụng macro ở đây bị lu mờ bởi những hạn chế. Có, nếu bạn sử dụng macro thì nếu bạn cần thêm thông số mẫu bổ sung, bạn sẽ chỉ cần thực hiện một sửa đổi duy nhất. Nhưng bất cứ ai khác đọc mã của bạn có lẽ sẽ nôn mửa.

Ý tôi là, bạn sẽ thực hiện việc này cho mỗi mẫu bạn có? Mã của bạn sẽ bị nhiễm các macro xấu xí.

+0

+1 và khá nhiều những gì tôi đã gõ khi bạn nhấn nút. :) –

1

có bạn có thể nhưng đừng quên sử dụng "#undef DFLT_TEMPLATE" và "#undef DFLT_CLASS" ở phần cuối của tập tin để tránh các cảnh báo trình biên dịch nếu dự án của bạn có một vài mẫu với cùng một macro các định nghĩa

0

Tôi sẽ xem xét phương pháp tiếp cận xấu này. Những gì bạn đang phàn nàn là bạn đã thay đổi thiết kế của mình (bạn cần thêm thông số mẫu) và bây giờ muốn có một kludge để lưu khi nhập?

Giới thiệu các macro sẽ giảm khả năng đọc mã của bạn. Các định nghĩa tiền xử lý chắc chắn có vị trí của chúng, nhưng cá nhân tôi sẽ không bao giờ bênh vực một với lý do là tôi không thể bị thay đổi chức năng của mình.

1

Thừa kế tốt hơn macro.

Nếu bạn muốn thay đổi chỉ một vài chức năng và biến, làm cho lớp chuyên biệt kế thừa một lớp chung cung cấp các hàm/biến chung.

0

Có thể có một số cách giải quyết (ít nhiều hay ít), nhưng bạn chắc chắn chỉ ra một tính năng "thiếu" của C++: class namespace extension.
Một số người đã đề xuất mở rộng C++ theo cách này:
http://www.lrde.epita.fr/dload//20080709-Seminar/ordy-classnamespaces.pdf

namespace foo 
{ 
    class bar 
    { 
    typedef int baz_t; 
    baz_t my_method(); 
    }; 
} 
namespace class foo::bar 
{ 
    baz_t my_method() 
    { 
    // ... 
    } 
} 

-
Sử dụng macro không phải là một ý tưởng tốt (những thứ bình thường về macro ....). Tôi thích, tệ nhất là viết các định nghĩa thành viên hàm trong trường hợp này, hoặc thậm chí sử dụng trình soạn thảo tốt hơn là có thể giúp bạn dễ dàng cập nhật định nghĩa lớp của mình.

Macro là xấu bởi vì chúng cho phép bạn viết các chức năng chỉnh sửa mã nơi bạn có nghĩa vụ viết chương trình. Nếu bạn muốn chỉnh sửa mã, hãy sử dụng trình soạn thảo của bạn (sed, M-x replace- *, Tìm & Thay thế ...)

2

Có bao nhiêu chức năng thành viên bạn có rằng đây là vấn đề không?

Tôi nghĩ rằng một trong hai chúng đủ nhỏ để có thể được định nghĩa trong lớp mẫu hoặc thích ứng của thuật toán của họ đến một tham số mẫu bổ sung sẽ do vượt xa việc thay thế những chức năng tiêu đề.

Ngoài ra, trình chỉnh sửa của bạn cũng nên thực hiện việc này cho bạn trong thời gian ngắn.

+0

Về gia công phần mềm, tôi nghĩ rằng việc gọi các chức năng được định nghĩa bên ngoài cũng sẽ tốt: cung cấp một phiên bản mẫu và cho phép mọi người quá tải nó cho các loại tùy chỉnh của họ nếu họ muốn. Sau khi tất cả những gì 'Boost' làm cho' hash_value', ví dụ, và đó là những gì chúng ta đã sử dụng cho 'swap'. –

1

Càng nhiều càng tốt, hãy đặt các định nghĩa hàm trong định nghĩa mẫu lớp. Đó là một mẫu, do đó, trừ khi bạn đang sử dụng trình biên dịch Comeau, nó không phải là nếu họ sẽ được tắt trong một TU khác nhau.

Nếu các hàm sử dụng thứ gì đó được định nghĩa ở giữa định nghĩa lớp và định nghĩa hàm, thì bạn có thể chơi thủ thuật để làm điều đó phụ thuộc vào tham số mẫu ngay cả khi "thực sự". Ví dụ:

template <typename T> 
struct Foo { 
    void usebar(); 
}; 

struct Bar { 
    int a; 
    Foo<int> circularity; // circular dependency between Foo and Bar 
    Bar() : a(3) {} 
}; 

template <typename T> void Foo<T>::usebar() { 
    Bar b; 
    std::cout << b.a << "\n"; 
} 

trở thành:

// we only have to write "same" once 
template <typename T, typename U> 
struct same { 
    typedef U type; 
}; 

struct Bar; 

template <typename T> 
struct Foo { 
    void usebar() { 
     typename same<T,Bar>::type b; 
     std::cout << b.a << "\n"; 
    } 
}; 

struct Bar { 
    int a; 
    Foo<int> circularity; // circularity gone 
    Bar() : a(3) {} 
}; 

Hoặc thực sự trong trường hợp này chỉ là:

struct Bar; 

template <typename T, typename B = Bar> 
struct Foo { 
    void usebar() { 
     B b; 
     std::cout << b.a << "\n"; 
    } 
}; 

struct Bar { 
    int a; 
    Foo<int> circularity; 
    Bar() : a(3) {} 
}; 

Mọi trường hợp hỗ trợ các đoạn mã sau:

int main() { 
    Foo<int> f; 
    f.usebar(); 
} 
Các vấn đề liên quan