2013-08-06 17 views
7

私はオブジェクトを持っています。このオブジェクトの各メンバ変数は、get_name()を呼び出して取得できる名前を持っています。メンバー変数をアルファベット順に並べ、次に何かをします。例えば:コピー&ペーストプログラミングの代わりに関数

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; 
... 
} 

私はこのようなハードコードする必要があります。

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

私は、オブジェクトが変化した場合に代わりにコピー&ペーストでこれを行うための機能を必要としています。誰でもアイデアがありますか?

+0

さまざまなメンバー変数を持つさまざまなオブジェクトがありますか? – doctorlove

+2

多分あなたはこれのためにいくつかのコレクションを使用することができますか?多分ベクトル。例:クラスオブジェクト{/*....*/ vector > some_vars /*....*/} /*....*/ for(auto&it:o.some_vars {sign + = it。 get_name;})または多分辞書/マップ –

+1

それは関数とより多くの*反射*です。 C++である程度のリフレクションを提供する方法はありますが、もしそれがなければ最善の方法です。 –

答えて

2

通常のC++でこれを行う方法の1つは、すべてのメンバーが同じクラスに属しているか、いくつかの基本クラスから派生している場合、関数に対して可変数の引数を使用することです。例を次に示します。

#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); 
} 

すべてのメンバーの種類が異なっている場合は、C++ 11Xの可変長引数テンプレートに見ることができます:http://en.wikipedia.org/wiki/Variadic_Templatesが、私はそうやるための方法を見つけるように見えることはできません。

+0

これは完璧な解決策ではありませんが、重複したコードをたくさん削除することができます。私はベクトルを使用してforループの文字列を保持し、アルファベット順にソートしてから連結することができます。ありがとう! – jfly

-2

この「観察パターン」のように見える、あなただけのメンバ変数としてオブジェクト内の単一のコピーを保持する必要がある「という文字列名_;」、およびこのようCXMLWrapperにname_sの参照を渡す:

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

あなたのコードは非常に危険で、ノーマルが必要な文脈では使用できません。 'CXMLWrapper'と' obejct'を割り当てることができないように、参照を使って作業します。 –

+1

私はそこにオブザーバーパターンを見ません – doctorlove

+0

@JanHerrmann私は危険はないと私はあなたが意味するものは "割り当てられない"ことを明確ではありません - あなたは3/5/0のルールについて話しています? – doctorlove

0

nameの変数が同じ型(またはこれらの型が1つの階層に属する)の場合、これらの変数のマップを使用できます。良い方法はありませんが、多分それはあなたが私の書き込みミスのため申し訳ありませんPS

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; 

に役立ちます。私の母国語ではない英語。

+1

このコードを使用すると、文字列型のコードが実行されます。おそらくメンバ変数を実際のメンバ変数としたいと思うかもしれません。普通の使用のために名前でマップに隠されていないだけです。 – doctorlove

+0

@Dark_Daiverはおかげさまで感謝していますが、引数が渡されているのでオブジェクトのレイアウトを変更できません。 – jfly

0

一つの方法は、メンバー名の外部ライブラリを持つことである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; 
    ... 
}; 

これは、オブジェクトの構築にオーバーヘッドを追加しないが、それは唯一のコンストラクタだとして、オーバーヘッド、それは影響を与えない可能性がありますシステム全体のパフォーマンスが大幅に向上します。

+0

答えをありがとうが、私はレイアウトやCXMLWrapperの階層を変更できません。 'BaseXMLWrapper'は良いアイデアです! – jfly

関連する問題