2012-12-11 25 views
6

đăng ký lớp tự động trong C++ là một nhiệm vụ phổ biến, và một câu hỏi thường được hỏi ở đây trên StackOverflow:Scalable đăng ký lớp tự động trong C++

Register an object creator in object factory

Somehow register my classes in a list

automatic registration of object creator function with a macro

c++ automatic factory registration of derived types

Mục tiêu cơ bản là đăng ký er lớp học tự động với một số đăng ký hoặc nhà máy để nó có thể làm một số công việc với mỗi lớp sau này.

Đây là một kỹ thuật tốt được thành lập, được sử dụng bởi các thư viện tương tự (ví dụ) Google thử nghiệm (http://code.google.com/p/googletest), tự động đăng ký các lớp con của lớp thử nghiệm để mỗi bài kiểm tra có thể được khởi tạo tự động và chạy trong quá trình thực thi.

Đăng ký có thể được thực hiện bằng cách khởi tạo lớp đăng ký tĩnh có hàm tạo đăng ký hoặc sử dụng thông minh CRTP và đặt mã đăng ký trong hàm tạo lớp cơ sở hoặc bất kỳ thứ gì bạn thích. kỹ thuật).

Tuy nhiên, khi tôi triển khai bất kỳ kỹ thuật nào trong số này, tôi thấy chúng có quy mô rất kém. Nếu tôi có 10.000 lời gọi macro TEST trong Google Test, việc biên dịch và liên kết xay sẽ dừng lại (MSVC 2010) và kích thước nhị phân sẽ phát nổ. Nếu tôi thực hiện điều này theo cách khác, sử dụng 10.000 lớp con với đăng ký tĩnh, tôi sẽ thấy hành vi tương tự.

Ví dụ, hãy xem xét các ví dụ đơn giản:

#include <iostream> 
#include <string> 

class Base { 

    public: 

     Base(const std::string& Name_) : Name(Name_) { ; } 
     ~Base() { ; } 

     virtual std::string GetName() const { return Name; } 
     virtual void DoSomething() = 0; 

    private: 

     std::string Name; 

}; 

class Registry { 

    public: 

     static Registry& GetInstance() { 
      static Registry* Instance = new Registry(); 
      return *Instance; 
     } 

     void Register(const Base* b) { 
      std::cout << "Registered class " << b->GetName() << std::endl; 
     } 

    private: 

     Registry() { ; } 
     ~Registry() { ; } 

}; 

class Registrar { 

    public: 

     Registrar(const Base* b) { 
      Registry::GetInstance().Register(b); 
     } 

     ~Registrar() { } 

}; 


#define REGISTER(CLASS)           \ 
    class CLASS : public Base {          \ 
     public:              \ 
      CLASS(const std::string& Name) : Base(Name) { ; } \ 
      virtual void DoSomething();        \ 
     private:             \ 
      static Registrar m_Registrar;       \ 
    };                \ 
    Registrar CLASS::m_Registrar(new CLASS(#CLASS));   \ 
    void CLASS::DoSomething() 


int main(int argc, char** argv) 
{ 
    return 0; 
} 


REGISTER(Class1) 
{ 
    std::cout << "Doing something in Class1" << std::endl; 
} 

REGISTER(Class2) 
{ 
    std::cout << "Doing something in Class2" << std::endl; 
} 

[...] 

với tổng số 10.000 cuộc gọi REGISTER autogenerated.

Có lý do cơ bản nào khiến điều này không mở rộng tốt không? Trình biên dịch có bị nghẹt thở trên 10000 lớp không? Theo MSVC 2010, việc biên dịch các bước trên mất gần hai phút trên một máy khá nhanh và tạo ra một tệp nhị phân có dung lượng trên 5 MB. Nếu tôi làm tương tự với Google Test, tôi thấy kết quả tương tự.

+2

Hãy chú ý đến sự khác biệt giữa một 'lớp' và một' đối tượng'. Mã này không ** không đăng ký các lớp (cũng không nên), nó đăng ký các đối tượng **. –

+0

Cảm ơn Pete. Đối với mục đích của tôi, như đối với Google Test, sẽ có một bản đồ một-một để tôi có thể chọn một kỹ thuật đăng ký, nhưng quan điểm của bạn là tốt. – DSII

+1

Không, không có ** nỗ lực lớn, bạn không thể đăng ký lớp học. –

Trả lời

1

Viết mã Java trong C++ hiếm khi hoạt động tốt. Tất cả những phân bổ đống đó có thể là hiệu suất giết chết (như trong Java, nhưng Java khởi động chậm đến mức không ai chú ý đến). Sử dụng các đối tượng tĩnh và không đặt đối tượng Registrar vào mỗi lớp được tạo; đó chỉ là một sự lãng phí thời gian và không gian.

+0

Cảm ơn Pete - nhưng tôi đã thử điều đó và điều đó không giúp ích gì. Nó có thể cạo 15 giây trong một thời gian biên dịch 2 phút và 200 kB tắt 5 MB nhị phân. Hiệu suất thời gian chạy không phải là vấn đề; bất kỳ triển khai nào tôi đã thử chạy đủ nhanh. – DSII

+0

Chỉ cần rõ ràng, về cơ bản bạn đang đề xuất có các instantiation tĩnh đơn của mỗi lớp dẫn xuất, và việc khởi tạo lớp cơ sở thực hiện việc đăng ký, đúng không? Tôi thực sự đã thử điều đó, và nó hoạt động giống hệt nhau. – DSII

+0

Ồ, bạn đang nói về thời gian biên dịch? Không, tôi không nghĩ có nhiều thứ bạn có thể làm ở đó. Đăng ký tự động phụ thuộc vào việc xây dựng các đối tượng và điều đó có nghĩa là tạo một đối tượng cho mọi thứ cần được đăng ký. –

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