2013-05-27 168 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); 
    // ... 
} 

这是一个可能对某些用途实际上有用的解决方案,但是我可能会嵌入脚本语言。