C ++ - based design a special case

  Now, the need to design a hypothetical JSON type data structure, good ideas ahead of you, roughly thought:

Object {
    "key": Boolean,
    "key": Number,
    "key": String,
    "key": Array,
    "key": Object
}

  Ah, it seems no problem, began to design ... did not write long, you may consider this situation:

Object {
    "key": [Object{}, Object{}, ...]
}

  This means that the class structure probably become like this:

class Object {
    bool boolean;
    double number;
    std::string string;
    std::vector<Object> array;
    Object object;
}

  Of course, you understand Object is a multi-value pairs, then change it:

class Value {
public:
    bool boolean;
    double number;
    std::string string;
    std::vector<Object> array;
    Object object;
};

class Object {
public:
    std::vector<std::pair<std::string key, Value value>>> objects;
}

  This is a class that contains another, for C ++, it is clear that the compiler will complain because the Value class using an undefined Object type, and where the compiler can not determine the size of your Value class member variables.

  However, you still have a way to use the pointer, and the Object class forward declaration:

class Object;

class Value {
public:
    bool boolean;
    double number;
    std::string string;
    std::vector<Object> array;
    Object* object;
};

class Object {
public:
    std::vector<std::pair<std::string, Value>>> objects;
}

  However, at this time and there will be a small problem, so if you want to use the interface as below

Object object;

object["Window"] = Value(Object("Color", Value("blue")));
std::cout << object["Window"].GetObject()["Color"].GetString();

  Is not feasible, because the object is a pointer to the Value, when overloaded [] operator can only use it:

Object object;

object["Window"] = Value(new Object("Color", Value("blue")));
std::cout << object["Window"].GetObject()->operator[]("Color").GetString();

  Looks very strange, if just live with what's fine, but from a different location would have been better:

class Value;

class Object {
public:
    std::vector<std::pair<std::string, Value*>>> objects;
}

class Value {
public:
    bool boolean;
    double number;
    std::string string;
    std::vector<Object> array;
    Object object;
};

  Usage becomes:

Object object;

object["Window"] = new Value(Object("Color", Value("blue")));
std::cout << object["Window"]->GetObject()["Color"]->GetString();

  If you want to completely get rid of this problem contains pointers need to do some work, inheritance + friend class by the middle class can be done to remove a very perfect look, see Microsoft open source cpprestsdk json code.

  Of course, maybe there are other ways to solve this problem, but I think the most beautiful and best embody the style of C ++ is to inherit + friend class.

  This blog just want to write when he started writing this class structural design problems encountered JSON structure / analyzer, although only mention here the use of forward class declaration, in fact, in addition to the type of problem to open a digital value (int64 -> int32 -> double overflow), performance problems, was also learned a lot of C ++ usage. (The future may be less use of C ++)

  Finally, give a minimalist JSON constructor to achieve:

#include <iostream>
#include <vector>
#include <string>

class Value;

class Boolean {
private:
	bool _boolean;
public:
	Boolean()
		: _boolean() {}
	Boolean(bool val)
		: _boolean(val)
	{

	}

	bool GetVal() const {
		return _boolean;
	}

	void SetVal(bool val)
	{
		_boolean = val;
	}
};

class Number {
private:
	double _number;
public:
	Number()
		: _number() {}
	Number(int val)
		: _number(val)
	{

	}
	Number(double val)
		: _number(val)
	{

	}

	double GetVal() const {
		return _number;
	}

	void SetVal(double val) {
		_number = val;
	}
};

class String {
private:
	std::string _string;
public:
	String() {}
	String(const char* val)
		: _string(val)
	{

	}
	String(std::string val)
		: _string(val)
	{

	}
	std::string GetVal() const {
		return _string;
	}

	void SetVal(std::string val)
	{
		_string = val;
	}
};

class Array {
private:
	std::vector<Value> _array;
public:
	Array()
		: _array()
	{
	}
	Array(std::vector<Value> val)
		: _array(val)
	{

	}
	std::vector<Value> GetVal() const
	{
		return _array;
	}

	void SetVal(std::vector<Value> val)
	{
		_array = val;
	}
};


class Object {
	std::vector<std::pair<std::string, Value*>> _elements;
private:
	typedef std::vector<std::pair<std::string, Value*>>::iterator iterator;

	iterator find_iter_by_key(std::string key)
	{
		return std::find_if(_elements.begin(), _elements.end(), [&key](const std::pair<std::string, Value*>& p) { return p.first == key; });
	}

public:
	Object() {}
	Object(std::string key, Value* value)
		: _elements{ {key, value} }
	{

	}

	Value*& operator[](std::string key)
	{
		return GetValue(key);
	}

	size_t Size() const
	{
		return _elements.size();
	}

	Value*& GetValue(std::string key)
	{
		auto iter = find_iter_by_key(key);
		if (iter == _elements.end())
			return _elements.insert(iter, std::pair<std::string, Value*>(key, nullptr))->second;
		return iter->second;
	}
};

class Value {
	Boolean v_boolean;
	Number v_number;
	String v_string;
	Array v_array;
	Object v_object;

public:
	Value()
		: v_boolean(), v_number(), v_string(), v_array(), v_object()
	{
	}

	Value(const Value & value)
	{
		*this = value;
	}

	Value(bool value)
		: v_boolean(value), v_number(), v_string(), v_array(), v_object()
	{

	}
	Value(int value)
		: v_boolean(), v_number(value), v_string(), v_array(), v_object()
	{

	}
	Value(double value)
		: v_boolean(), v_number(value), v_string(), v_array(), v_object()
	{

	}
	Value(std::string value)
		: v_boolean(), v_number(), v_string(value), v_array(), v_object()
	{

	}
	Value(std::vector<Value> value)
		: v_boolean(), v_number(), v_string(), v_array(value), v_object()
	{
	}
	Value(Boolean value)
		: v_boolean(value), v_number(), v_string(), v_array(), v_object()
	{

	}
	Value(Number value)
		: v_boolean(), v_number(value), v_string(), v_array(), v_object()
	{

	}
	Value(String value)
		: v_boolean(), v_number(), v_string(value), v_array(), v_object()
	{

	}
	Value(Array value)
		: v_boolean(), v_number(), v_string(), v_array(value), v_object()
	{

	}
	Value(Object value)
		: v_boolean(), v_number(), v_string(), v_array(), v_object(value)
	{

	}

	bool GetBoolean() const
	{
		return v_boolean.GetVal();
	}

	double GetNumber() const
	{
		return v_number.GetVal();
	}

	int Tinted Number () const {
		return (int)v_number.GetVal();
	}

	std::string GetString() const
	{
		return v_string.GetVal();
	}

	std::vector<Value> GetArray() const
	{
		return v_array.GetVal();
	}

	Object GetObject() const
	{
		return v_object;
	}

	Value& GetValue()
	{
		return *this;
	}


};

int main ()
{
	Object object("test", new Value(Object("abc", new Value(123))));
	object["color"] = new Value(Array{ std::vector<Value>{ Value(String("red")), Value(String("orange")), Value(String("yellow")) } });
	std::cout << object["test"]->GetObject()["abc"]->GetIntNumber() << '\n';
	for (auto i : object["color"]->GetArray())
		std::cout << i.GetString() << " ";
	return 0;
}

  Output:

123
red orange yellow

  

Guess you like

Origin www.cnblogs.com/darkchii/p/12563533.html