C ++ - 特殊なケースに基づいた設計

  今、必要があなたの前に、良いアイデアを仮想的なJSON型のデータ構造を設計するために、およそ考えました:

オブジェクト{ 
    「キー」:ブール、
    「キー」:番号、
    「キー」列、
    「キー」配列、
    「キー」:オブジェクト
}

  ああ、それは何の問題もないようだ、...長く書いていない、あなたがこのような状況を考慮することができる設計し始めました。

オブジェクト{ 
    "キー":[オブジェクト{}、オブジェクト{}、...] 
}

  クラス構造は、おそらくこのようになることをこれは意味:

クラスObject { 
    BOOLブール。
    二重の数; 
    std ::文字列string; 
    std ::ベクトル<オブジェクト>配列。
    Objectオブジェクト。
}

  もちろん、あなたがオブジェクトを理解するマルチ値のペアで、それを変更します。

クラス値{ 
パブリック:
    ブールブール。
    二重の数; 
    std ::文字列string; 
    std ::ベクトル<オブジェクト>配列。
    Objectオブジェクト。
}。

クラスObject { 
パブリック:
    のstd ::ベクトル<スタンダード::ペア<のstd ::文字列キー、バリュー値>>>オブジェクト。
}

  これは、C ++のために、コンパイラは未定義のオブジェクトタイプを使用して、バリュークラスので文句を言うだろう、とどこコンパイラは、あなたのバリュークラスのメンバ変数のサイズを決定することができないことは明らかである、別のものを含むクラスです。

  しかし、あなたはまだ、ポインタを使用する方法、およびObjectクラス前方宣言を持っています。

クラスObject。

クラス値{ 
パブリック:
    ブールブール。
    二重の数; 
    std ::文字列string; 
    std ::ベクトル<オブジェクト>配列。
    *オブジェクトです。
}。

クラスObject { 
パブリック:
    のstd ::ベクトル<スタンダード::ペア<のstd ::文字列、値>>>オブジェクト。
}

  しかし、この時点で、あなたは以下のようにインターフェイスを使用したいのであれば、小さな問題があるだろう

Objectオブジェクト。

オブジェクト[ "ウィンドウ"] =値(オブジェクト( "カラー"、値( "青")))。
std :: COUT <<オブジェクト[ "ウィンドウ"]のGetObject() "カラー"]のGetString()。。。

  オブジェクトが値へのポインタであるため、現実的ではありません、オーバーロードされたとき、[]演算子は、それを使用することができます。

Objectオブジェクト。

オブジェクト[ "ウィンドウ"] =値(新しいオブジェクト( "カラー"、値)( "青"))。
std :: COUT <<オブジェクト[ "ウィンドウ"]のGetObject() - >演算子[]( "カラー")のGetString()。。。

  ルックスは非常に奇妙な、細かいですが、別の場所から良くなっているだろうかとばかり住んでいる場合:

クラス値; 

クラスObject { 
パブリック:
    のstd ::ベクトル<スタンダード::ペア<のstd ::文字列、値* >>>オブジェクト。
} 

クラス値{ 
パブリック:
    BOOLブール。
    二重の数; 
    std ::文字列string; 
    std ::ベクトル<オブジェクト>配列。
    Objectオブジェクト。
}。

  使用法は次のようになります。

Objectオブジェクト。

オブジェクト[ "ウィンドウ"] =新しい値(オブジェクト( "カラー"、値)( "青"))。
std :: COUT <<オブジェクト[ "ウインドウ"] - >のGetObject() "カラー"] - >のGetString();

  あなたは完全にこの問題を取り除くためにしたい場合は、ポインタは、非常に完璧な外観を削除し、マイクロソフトのオープンソースを参照するために行うことができます中産階級によって、継承+友人のクラスをいくつかの作業を行う必要があります含まれていcpprestsdkの JSONコードを。

  もちろん、多分そこにこの問題を解決するための他の方法がありますが、私はC ++のスタイル具現化で最も美しいと最高の継承+友人のクラスにあると思います。

  > INT32 - 彼は唯一(Int64の問題のタイプに加えて、デジタル値を開くために、実際には、ここでは前方クラス宣言の使用に言及が構造設計上の問題は、JSON構造/アナライザに遭遇し、このクラスを書き始めたときに、このブログはちょうど書きたいです - >ダブルオーバーフロー)、パフォーマンスの問題は、また、C ++の使用の多くのことを学びました。(将来は、C ++のより少ない使用であってもよいです)

  最後に、達成するためのミニマリストのJSONコンストラクタを与えます:

書式#include <iostreamの> 
の#include <ベクトル> 
の#include <文字列> 

クラス値。

クラスブール{ 
プライベート:
	ブール_boolean。
公共:
	ブール()
		:_boolean(){} 
	ブール(ブールヴァル)
		:_boolean(ヴァル)
	{ 

	} 

	BOOL GETVAL()constは{ 
		_boolean返します。
	} 

	ボイドSETVAL(BOOLヴァル)
	{ 
		_boolean =ヴァル。
	} 
}。

クラス数{ 
プライベート:
	ダブル_number。
公共:
	番号()
		:_number(){} 
	番号(INTヴァル)
		:_number(ヴァル)
	{ 

	} 
	の数(二重ヴァル) 
		:_number(ヴァル)
	{ 

	} 

	ダブルGETVAL()constは{ 
		戻り_number。
	} 

	ボイドSETVAL(ダブルヴァル){ 
		_number =ヴァル。
	} 
}。

クラス文字列{ 
プライベート:
	STD ::文字列_string。
公共:
	文字列(){} 
	文字列(CONST CHAR *ヴァル)
		:_string(ヴァル)
	{ 

	} 
	文字列(のstd ::文字列ヴァル)
		:_string(ヴァル)
	{ 

	} 
	はstd ::文字列GETVAL()constは{ 
		戻り_string。
	} 

	ボイドSETVAL(スタンダード::文字列のval)
	{ 
		_string =ヴァル。
	} 
}。

クラスArray {
公衆: 
プライベート:
	std ::ベクトル<値> _array。
	アレイ()
		:_array()
	{ 
	} 
	アレイ(スタンダード::ベクトル<値>ヴァル)
		:_array(ヴァル)
	{ 

	} 
	のstd ::ベクトル<値> GETVAL()constは
	{ 
		戻り_array。
	} 

	ボイドSETVAL(スタンダード::ベクトル<値>ヴァル)
	{ 
		_array =ヴァル。
	} 
}。


クラスObject { 
	STD ::ベクトル<スタンダード::ペア<のstd ::文字列、値* >> _elements。
プライベート:
	typedefでのstd ::ベクトル<はstd ::ペア<のstd ::文字列、値* >> ::イテレータイテレータ。

	イテレータfind_iter_by_key(STD ::文字列キー)
	{ 
		リターンのstd :: find_if(_elements.begin()、_elements.end()、[&キー(CONSTのstd ::ペア<のstd ::文字列、値*>&P){リターンp.first ==キー;});

公共:
	オブジェクト(){} 
	オブジェクト(スタンダード::文字列キー、値*値)
		:_elements {{キー、値}} 
	、{ 

	} 

	値*&演算子[](スタンダード::文字列キー)
	{ 
		GetValueメソッド(キー)を返します。
	} 

	size_tのサイズ()constは
	{ 
		戻り_elements.size()。
	} 

	値*&GetValueメソッド(スタンダード::文字列キー)
	{ 
		オートITER = find_iter_by_key(キー)。
		(ITER == _elements.end())であれば
			、戻り_elements.insert(ITER、STD ::ペア<のstd ::文字列、値*>(キー、nullptr)) - >第二; 
		二> iter-を返します。
	}
}。

クラス値{ 
	ブールv_boolean。
	番号v_number。
	文字列のv_string。
	アレイv_array。
	オブジェクトv_object。

公共:
	値() 
		:)(v_boolean、v_number(値))(v_string、v_array()、v_object()
		:)(v_boolean、v_number())(v_string、v_array()、v_object()
	{ 
	} 

	値(バリュー&値CONST)
	{ 
		*この=値。
	} 

	値(ブール値)
		:v_boolean(値)、v_number())(v_string、v_array()、v_object()
	{ 

	} 
	の値(整数値)
		:v_boolean()、v_number(値))(v_string、v_array( )、v_object()
	{ 

	} 
	値(二値) 
	値(STD ::ベクター<値>値)
		:v_boolean()、v_number())(v_string、v_array(値)、v_object()
	{ 

	} 
	値(スタンダード::文字列値)
		:v_boolean()、v_number()、v_string(値)、v_array()、v_object()
	{ 

	} 
	{ 
	} 
	値(ブール値)
		:v_boolean(値)、v_number()、 )(v_string、v_array()、v_object()
	{ 

	} 
	値(数値)
		:v_boolean()、v_number(値))(v_string、v_array()、v_object()
	{ 

	} 
	の値(文字列値)
		:v_boolean() 、v_number()、v_string(値)、v_array()、v_object()
	{ 

	} 
	値(配列値)
		:v_boolean()、v_number()、v_string()、v_array(値)、v_object()
	{ 

	} 
	値(オブジェクト値)
		:v_boolean()、v_number())(v_string、v_array()、v_object(値)
	{ 

	} 

	BOOL GetBoolean()constは
	{ 
		リターンv_boolean.GetVal()。
	}

	二重はgetNumber()constは
	{ 
		リターンv_number.GetVal()。
	} 

	INT GetIntNumber()constは{ 
		リターン(INT)v_number.GetVal(); 
	} 

	のstd ::文字列のGetString()constは
	{ 
		リターンv_string.GetVal()。
	} 

	のstd ::ベクトル<値>のgetArray()constは
	{ 
		リターンv_array.GetVal()。
	} 

	オブジェクトのGetObject()constは
	{ 
		戻りv_object。
	} 

	値&GetValueメソッド()
	{ 
		*、これを返します。
	} 


}。

INTメイン()
{ 
	Objectオブジェクト( "試験"、新たな値(オブジェクト( "ABC"、新たな値(123))))。 
	オブジェクト[ "カラー"] =新しい値(配列{スタンダード::ベクトル<値> {値(文字列( "赤色"))、値(文字列( "オレンジ"))、値(文字列(「黄「))}})。
	std :: COUT <<オブジェクト[ "テスト"] - >のGetObject() "ABC"] - > GetIntNumber()<< '\ n'は、
	(自動I:オブジェクト[ "カラー"] - >のgetArray())のため
		のstd :: COUT << i.GetString()<< "「。
	0を返します。
}

  出力:

123 
赤オレンジ黄色

  

おすすめ

転載: www.cnblogs.com/darkchii/p/12563533.html