2013-08-06 52 views
7

Tôi có một đối tượng, mỗi biến thành viên trong đối tượng này có tên mà tôi có thể lấy nó bằng cách gọi hàm get_name(), những gì tôi muốn làm là nối tất cả các tên của biến thành viên theo thứ tự bảng chữ cái, sau đó làm điều gì đó. ví dụ:một hàm thay vì chương trình sao chép và dán

class CXMLWrapper<class T> 
{ 
public: 
    CXMLWrapper(const char* p_name) : m_local_name(p_name) 
    { 
    } 
    //skip the get_name(), set_name() and others  
private: 
    string m_local_name; 
    T m_type_var; 
} 
class object 
{ 
public: 
    object() : m_team("team"), m_base("base") 
    { 
    } 
public: 
    CXMLWrapper<string> m_team; 
    CXMLWrapper<string> m_base; 
... 
} 

tôi phải cứng mã như thế này:

object o; 
string sign = o.m_base.get_name(); 
sign += o.m_team.get_name(); 

Tôi cần một chức năng để làm điều này thay vì sao chép và dán khi đối tượng khác nhau. Bất cứ ai có một ý tưởng?

+0

Bạn có các đối tượng khác nhau với các biến thành viên khác nhau không? – doctorlove

+2

Có lẽ bạn có thể sử dụng một số bộ sưu tập cho điều này? Có lẽ vector. Ví dụ: đối tượng lớp {/*....*/ vector > some_vars /*....*/} /*....*/ cho (auto & it: o.some_vars {sign + = it. get_name;}) Hoặc có thể từ điển/bản đồ –

+1

Đó là một chức năng ít hơn và * phản ánh *. Có nhiều cách để cung cấp một mức độ phản ánh trong C++, nhưng nếu bạn có thể làm mà không có nó sẽ là tốt nhất. –

Trả lời

2

Một cách để thực hiện điều này trong C++ bình thường, miễn là tất cả các thành viên thuộc cùng một lớp hoặc có nguồn gốc từ một số lớp cơ sở sẽ sử dụng số biến đối số cho hàm. Một ví dụ sau.

#include <stdarg.h> 
string concatenateNames(int numMembers, ...) 
{ 
    string output; 
    va_list args; 
    va_start(args, numMembers); 
    for(int i = 0; i < numMembers; i++) 
    { 
     MemberClass *pMember = va_arg(args, MemberClass*); 
     output += pMember->get_name(); 
    } 
    va_end(args); 
    return output; 
} 

class Object 
{ 
    public: 
     MemberClass x; 
     MemberClass y; 
     MemberClass z; 
}; 

int main() 
{ 
    Object o; 
    string sign = concatenateNames(3, &o.x, &o.y, &o.z); 
} 

Nếu các loại của tất cả các thành viên là khác nhau, bạn có thể nhìn vào các mẫu variadic của C++ 11x: http://en.wikipedia.org/wiki/Variadic_Templates, nhưng tôi dường như không thể tìm thấy một cách để làm điều ngược lại.

+0

Mặc dù nó không phải là một giải pháp hoàn hảo, nhưng nó có thể loại bỏ rất nhiều mã trùng lặp. Tôi có thể sử dụng một vector để giữ các chuỗi trong vòng lặp for và sắp xếp chúng theo thứ tự bảng chữ cái, sau đó ghép nối. Cảm ơn! – jfly

-2

này trông giống như một "mô hình quan sát", bạn chỉ cần giữ một bản duy nhất trong đối tượng như là một biến thành viên "chuỗi name_;", và thông qua tham khảo của name_s vào CXMLWrapper như thế này:

class CXMLWrapper<class T> 
{ 
public: 
    CXMLWrapper(const string &name) 
     : local_name_(name) 
     { 
     } 
    //skip the get_name() set_name()  
    private: 
     const string &local_name_; 
} 

class object 
{ 
public: 
    object() 
     : team_("team"), 
      base_("base"), 
      m_team(team_) 
     , m_base(base_) 
     { 
     } 
public: 
    string team_; 
    string base_; 
    CXMLWrapper<string> m_team; 
    CXMLWrapper<string> m_base; 
} 
+0

Mã của bạn ** rất nguy hiểm và không thể sử dụng được trong ngữ cảnh mà nó cần phải có. Bạn làm việc với các tham chiếu vì vậy không thể chỉ định 'CXMLWrapper' và' obejct'. –

+1

Tôi không thấy mẫu người quan sát ở đó – doctorlove

+0

@JanHerrmann Tôi không thấy nguy hiểm và tôi không rõ ý bạn là gì "không thể được chỉ định" - bạn nói về quy tắc ba/năm/số không ? – doctorlove

0

Nếu các biến có tên có cùng một loại (hoặc các loại này thuộc về một phân cấp), bạn có thể sử dụng bản đồ của các vars này. không phải là cách tốt, nhưng có lẽ nó giúp bạn

Ví dụ

class object 
{ 
public: 
    object() //: m_team("team"), m_base("base") 
    { 
     this->vars["m_team"] = CXMLWrapper<string>("team"); 
     //..... 
    } 
public: 
    map<string, CXMLWrapper<string> > vars; 
    /*CXMLWrapper<string> m_team; 
    CXMLWrapper<string> m_base;*/ 
... 
} 

object o; 
string sign; 
for(auto& x : o.vars)//i cannot remember syntax of for of map 
    sign += x.get_name; 

PS Xin lỗi vì viết sai lầm của tôi. Tiếng Anh không phải là ngôn ngữ mẹ đẻ của tôi.

+1

Sử dụng mã này sẽ thực thi mã hóa được nhập bằng chuỗi. Bạn có thể muốn biến thành viên như biến thành viên thực tế, không chỉ ẩn trong bản đồ theo tên để sử dụng bình thường – doctorlove

+0

@Dark_Daiver cảm ơn gợi ý, nhưng tôi không thể thay đổi bố cục của đối tượng vì nó là đối số được truyền cho tôi. – jfly

0

Một phương pháp là phải có một thư viện bên ngoài tên thành viên mà các bản cập nhật lớp CXMLWrapper: -

class BaseXMLWrapper 
{ 
public: 
    void ListMembers (const char *parent) 
    { 
    // find "parent" in m_types 
    // if found, output members of vector 
    // else output "type not found" 
    } 
protected: 
    void RegisterInstance (const char *parent, const char *member) 
    { 
    // find 'parent' in m_types 
    // if not found, create a new vector and add it to m_types 
    // find 'member' in parent vector 
    // if not found, add it 
    } 
private: 
    static std::map <const std::string, std::vector <const std::string> > 
    m_types; 
}; 

class CXMLWrapper <class T, const char *parent> : BaseXMLWrapper 
{ 
public: 
    CXMLWrapper(const char* p_name) : m_local_name(p_name) 
    { 
    RegisterInstance (parent, p_name); 
    } 
    // you could override assignments, copy and move constructors to not call RegisterInstance 
    //skip the get_name() set_name()  
private: 
    m_local_name; 
} 

class object 
{ 
public: 
    object() : m_team("team"), m_base("base") 
    { 
    } 
public: 
    CXMLWrapper<string, "object"> m_team; 
    CXMLWrapper<string, "object"> m_base; 
    ... 
}; 

này thêm nguyên cần thiết để xây dựng các đối tượng, nhưng khi nó chỉ là một nhà xây dựng trên cao nó có thể không ảnh hưởng đến hiệu suất hệ thống tổng thể nhiều.

+0

Cảm ơn câu trả lời nhưng tôi không thể sửa đổi bố cục hoặc cấu trúc phân cấp của 'CXMLWrapper'. 'BaseXMLWrapper' là một ý tưởng hay! – jfly

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