2013-05-27 169 views
1

使用控制檯應用程序時,我試圖找出一種允許用戶輸入對象屬性和值的方法。例如動態更改C++中類的屬性

class Box{ 
    public: 
    int height; 
    int width; 
    int length; 
}; 

int main(){ 
    string memberName,value 
    cin>>memberName>>value; 
} 

如果用戶輸入的高度,然後通過使用成員名稱和價值我如何改變高度的價值,無論用戶輸入。我想做這個工作,以便可以添加另一個類並獲得相同的功能。

我在考慮使用地圖,但並不完全知道我將如何繼續這樣做。

回答

0

使用地圖確實是這樣做的方式。將代碼示例

#include "stdafx.h" 
#include <iostream> 
#include <map> 
#include <string> 





int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::map<std::string,std::string> mapData; 


    std::string name,value; 
    std::cout << "Enter Name:\n"; 
    std::cin >> name; 
    std::cout << "\n\nEnter Data\n"; 
    std::cin >> value; 

    mapData[name] = value; 

    return 0; 
} 

不久編輯或者你可以有一個類包裝的地圖,如果你需要做的地圖上或之間的各種其它操作(如驗證輸入或其他操作與之前輸入你將它存儲在地圖中)。

// example of class wrapping a map 
class MapContainer { 
private: 
    map<string,string> _map; 

public: 
    void addValue(const string& name, const string& value) { 
     _map[name] = value; 
    } 

    string getValue(const string& name) { 
     return _map[name]; 
    } 


} 
+0

我還是有點迷路。這將如何改變對象的價值? – user2424954

+1

@ user2424954,把它想象成一個散列,你可以從字符串中訪問你的屬性。 – Lefsler

+0

所以在我的情況下,我會做一些像框a;屬於MapData [名稱] =值; a.mapData [name] = value?對於特定的問題,我很抱歉,我對C++ – user2424954

4

這裏做一個複雜的方式,但它正是你試圖在第一個地方做(輕鬆地將其應用到任何結構):

#include <iostream> 
#include <string> 
#include <map> 

///////////////////////////////////////// 
// HELPERS 
template<class T> 
class MemberPtrBase 
{ 
public: 
    virtual std::istream& Read(std::istream& is, T& object) = 0; 
    virtual ~MemberPtrBase() {} 
}; 
template<class T, class V> 
class MemberPtr : public MemberPtrBase<T> 
{ 
    V T::*member; 
public: 
    MemberPtr(V T::*ptr) 
     : member(ptr) 
    {} 
    std::istream& Read(std::istream& is, T& object) 
    { 
     return is >> (object.*member); 
    } 
}; 
template<class T> 
class MemberMap 
{ 
    typedef std::map<std::string, MemberPtrBase<T>*> MapType; 
    MapType members; 
public: 
    MemberMap() {} 
    ~MemberMap() 
    { 
     for (MapType::iterator it = members.begin(); it != members.end(); ++it) 
      delete it->second; 
    } 

    template<class V> 
    void Register(std::string const& name, V T::*ptr) 
    { 
     members[name] = new MemberPtr<T, V>(ptr); 
    } 

    std::istream& ReadValue(std::istream& is, T& object) 
    { 
     std::string name; 
     is >> name; 
     if (members.find(name) == members.end()) 
     { 
      std::cerr << "Unknown member: " << name << std::endl; 
      return is; 
     } 
     return members[name]->Read(is, object); 
    } 
}; 
/////////////////////////////////////////// 

class Box 
{ 
public: 
    int width; 
    int height; 
    int length; 

    static MemberMap<Box> members; 
}; 
MemberMap<Box> Box::members; 

class Circle 
{ 
public: 
    int x; 
    int y; 
    int radius; 

    static MemberMap<Circle> members; 
}; 
MemberMap<Circle> Circle::members; 

int main() 
{ 
    Box::members.Register("width", &Box::width); 
    Box::members.Register("height", &Box::height); 
    Box::members.Register("length", &Box::length); 
    Circle::members.Register("x", &Circle::x); 
    Circle::members.Register("y", &Circle::y); 
    Circle::members.Register("radius", &Circle::radius); 

    Box box; 
    Box::members.ReadValue(std::cin, box); 

    return 0; 
} 
0

簡單地說,你可以」不要以一般的方式去做;根據運行時的名稱無法訪問成員變量。

這通常是通過創建的if-else鏈解決(或交換機),它允許你轉換數據信息

char type; 
float height; 
int age; 

cin >> type; 
switch(type) { 
    case 'h': cin >> height; break; 
    case 'a': cin >> age; break; 
} 

這是不靈活,但這樣是你的階級結構,對?如果你想讓它變成動態的,像@ riv的回答那樣創建綁定是沒有意義的;班級的任何變化都需要適當的條款。這將是更好地簡單地決定,有些字段是動態存儲地圖:

class C { 
    int iAlwaysHaveThat; 
    map<variant<int,float,string>> dynamicValues; 
}; 

這樣,你可以解析配置文件,如:

Obj [ 
    a = 5, 
    b = 3.14, 
    name = "some string value" 
] 

然後通過(根據實際需要訪問它們)函數返回optional

optional<variant<...>> getDynamicValue(string const& name) { ... } 

這也可能填補違約基礎上一些其他的對象,例如:

{ 
    // ... 
    auto v = dynamicValues.find(name); 
    if (v == dynamicValues.end()) 
     return defaultValuesProvider.getDefault(name); 
    // ... 
} 

這是一個可能對某些用途實際上有用的解決方案,但是我可能會嵌入腳本語言。