U E D R , A S I H C RSS

More EffectiveC++/Basic

1. Basic

1.1. Item 1: Distinguish between pointers and references.

  • Item 1: Pointer™€ Referenceตฌ„ํ•ด.
    Pointers use the "*" and "->" operators, references use "."

Š‚Œด ˜คŠ” ˜ˆ œ“ค[[BR]]
~cpp 
    char *pc = 0;
    char& rc = *pc;
ํ”„กœทธž˜จธ ดˆธ‰žฉด •Œˆ˜ žˆŠ” ฐ”ณด ง“ด‹ค. ํ•˜€งŒ ฒ”ํ•˜ธฐ ‰ฌšดฒŒ ฌธ œ‹ค.
~cpp 
    string& rs;        // Reference(ฐธกฐ)€ ดˆธฐํ™”€ ˜€ •Š•„„œ —Ÿฌ

    string s("xyzzy"); // ดœ‹ค ‹ ธฐํ•˜„ค 
    string& rs = s;
•„ง stringจณธ  ํ•œฒˆ„ —†‹ค. ฐ˜„..
~cpp 
    void printDouble(const double& rd)
    {
        cout << rd;    // rd— €ํ•œ ํŠ„ํ•œ €‚ฌ ํ•„š” —†‹ค. reference‹ˆŒ.
    }
    ////////////////////////////////////////////////////////////////////
    void printDouble (const double* pd)
    {
        if (pd){
            cout << *pd    // pd€ nullธ€ €‚ฌ ํ•ด• ํ•œ‹ค. pointer‹ˆŒ.
        }
    }
pointer˜ œ ˜ ‚ฌํ•ญธ null— €ํ•œ ‚ดšฉ„ ‹ค‹œ •Œ ค€‹ค.
~cpp 
    string s1("Nancy");    // ด œŠ” ฌดŠจ ํ€ฆˆ ฐ™‹ค.
    string s2("Clancy");   
    string& rs = s1;
    string* ps = &s1;
    rs = s2;               // s1˜ ธž€ "Clancy" กœ ฐ”€‹คŠ” ˜‹ค.
    ps = &s2;              // ทธƒฅ ํฌธํ„งŒ „ธํŒ…ํ•˜Š” ‹ค. 
                           // ดกœ psŠ” s2 €ฆฌํ‚คณ  s1—Š” •„ฌดŸฐ ˜ํ–ฅ„ ˜€ •ŠŠ”‹ค.
‚ฌฒฌ: Call by Value ณด‹ค Call by Reference™€ Const˜ กฐํ•ฉ„ „ ํ˜ธํ•˜ž.  €ž˜ Effective C++—  „ฐ˜ œกœ –ธธ‰˜–ด žˆณ , ํ”„กœทธž˜ฐ„ ํ•ดณด‹ˆ ดœฐฎ€ ํŽธด—ˆ‹ค. ‹จ return—„œ งฝด ƒธฐŠ”ฐ, ํ˜„žฌ ‚ด ƒฐ€ return— Œ€ํ•ด„œ ํšŒ˜ ด‹ค. ทธž˜„œ ‚˜Š” COM‹ ํ‘œํ˜„ธ in, out  ‘‘–ด ‚ฌšฉํ•ด„œ •„˜ˆ ธž „˜ฒจ„œ €ฆฌํ•œ‹ค. C++˜ ฒฝšฐ return— ˜ํ•ด ฐฒด Call by Referenceํ•˜ฉด {} ฒ—–ด‚˜Š” …ˆด ˜Š”ฐ –ด””„œ ํŒŒดด˜Š” ฒƒธ€. ‹ค ณต€€ €ํ•ด„œ• ฉ --;
€—ญํ•จˆ˜ •ˆ—„œ €—ญ ฐฒด ƒ„ํ•˜—ฌ Referenceกœ ฆฌํ„ดํ•  ฒฝšฐ €—ญ ํ•จˆ˜€ ฐ˜ํ•œ˜ฉด €—ญ ฐฒดŠ” —†–ดงˆ ฒƒดณ , ฆฌํ„˜Š” ReferenceŠ” กดžฌํ•˜€ •ŠŠ” ฐฒด— Œ€ํ•œ ‹คฅธ ด„ด   ฒƒดฉฐ, ฒฝšฐ— ”ฐ„œ ปดํŒŒ€  €ชจฅด‚˜ ‚˜œ ฝ”“œณ  ํ•˜„š”.-ฐจ„ญ-
˜คํ•ด˜ †Œ€€ žˆ„ก €„  –ด †จตฐš”. in, out  ‘‘–ด ดšฉํ•ด„œ referenceกœ „˜ธธ ธž“ค—„œŠ” in— ํ•œํ•˜—ฌ reference, out€ pointerกœ new, deleteกœ ™ œกœ €ฆฌํ•˜Š”ฒƒ„ ˜„ํ•œ งด—ˆŠต‹ˆ‹ค.  „— ํ”„กœ ํŠธ— ดŸฐ‹˜ ํ”„กœทธž˜ฐ„  šฉ ‹œŠ”ฐ, ํ•จˆ˜ ‚ด€—„œ ํฌธํ„กœ ‚ฌšฉํ•˜Š” ฒƒณด‹ค in— ํ•ด‹ํ•˜Š” ฐฒด ‚ฌšฉ ฝ””ฉด ํŽธํ•˜”ตฐš”. ทธฆฌณ  ง”€ํ•˜‹ Œ€กœ, MEC++  „ฐ˜— €—ญฐฒดกœ ƒ„ํ•œ Referneceฌธ œ— €ํ•œ –ธธ‰ด žˆŠ”ฐ, ดฒƒ˜ €ฆฌ€ C++˜ €žฅ ํฐ ฒฝœกœ ž‘šฉํ•˜Š” ฒƒด •„‹Œ ƒฐด ฉ‹ˆ‹ค. OOP  ด คฉด ฐ˜ํ™˜„ ฐฒดกœ ํ•ด• ํ•˜Š”ฐ, ด ํฌธํ„กœ „˜ธฐŠ” ฒƒ€ ›™ œกœ ฐฒด „˜ธด‹คณ  ˆ˜ —†ณ , ํ•ด œ ฌธ œ€ ฐœƒํ•˜ฉฐ, referenceกœ „˜ธฐฉด ง”€ํ•˜‹ ฐกœ, ํ•ด‹ scope€ ฒ—–ด‚˜ฉด –ธ–ดƒ˜ lifetimeด ‚œ ฒƒด€กœ ˜—ญ— Œ€ํ•œ ฉ”ชจฆฌ  ‘„ OS—„œ ง‰„€„ ชจฆ…‹ˆ‹ค. ‹จ, inline— ํ•œํ•˜—ฌŠ” ด•ธฐ€ ‹ฌง‘‹ˆ‹ค. (inline˜ ฝ”“œ ตฒด€ compiler— ˜ํ•˜—ฌ ฒฐ •˜€กœ ดฒƒ„ —ญ‹œ ชจํ˜ธํ•ด ง‘‹ˆ‹ค.) •„˜ˆ COM—„œŠ” OOP—„œ ฒ—–ด ‚˜”„, ฒ”šฉ œกœ “ฐˆ˜ žˆ„ก CŠคํŽ™˜ ํ•จˆ˜™€ ฐ™ด in, out ˜  ‘‘–ด™€ ํ•ด‹  ‘‘–ดŠ” pointerกœ ํ•˜Š” ทœ™„ „›Œ†“•˜€š”. ด „„€ C#—„œ buil-in type˜ scalarํ˜•— ํ•ด‹ํ•˜Š” ฒƒŒ€ ฐ˜˜œ ฒƒด ธƒ ด —ˆŠต‹ˆ‹ค.(MS€ ดˆธฐ .net„‚˜—„œ ด •Œฌธ— String —ฐ‚ฐ ฐจด€ 10~20ฐฐ  •„ ‚œ‹คณ  ด‘ณ ํ•˜ณ  ‹ค…”—ˆŠ”ฐ, €ธˆ ƒฐํ•ด ณดฉด ‹ค €งˆ—†Š” ด•ธฐ ฐ™Šต‹ˆ‹ค.) -ƒ

1.2. Item 2 : Prefer C++ style casts.

  • Item 2 : C++ Šคํƒ€˜ ํ˜•€ํ™˜„ ถŒžฅํ•œ‹ค.
C style cast ฐฉฒ•
~cpp 
(type) expression 
C++ style cast
~cpp 
static_cast<type>(expression) 

const_cast<type>(expression)

dynamic_cast<type>(expression)

reinterpret_cast<type>(expression)

  • static_cast<type>(expression)Š” ธฐกด˜ C style—„œ ‚ฌšฉํ•˜Š” (type)expression ™€ ™ํ•˜‹ค.

‹คฅธ cast ฌธฒ•€ const™€ class€ ณ  คœ C++ style cast—ฐ‚ฐž ด‹ค.

  • const_cast<type>(expression)˜ˆ œ

~cpp 
class Widget{ ...}
class SpecialWidget:public Widget{...}
void update( SpecialWidget *psw);
SpecialWidget sw;
const SpecialWidget& csw = sw;

update(&csw);	// ‹—ฐํžˆ •ˆจ constธžด€กœ €ํ™˜(ํ’€–ดŠ” ) ‹œœ –ด• ํ•œ‹ค.

update(const_cast<SpecialWidget*>(&csw));	// ˜ณํƒ€ฟ ‚˜ 
update((SpecialWidget*)&csw);        // C styleธฐ ž˜ Œ•„„‹ค. 
                                     // C++Š” C™€˜ ํ˜ธํ™˜„ ณ  ค œ„ํ•œ ฒƒด€กœ œ„™€ ฐ™ด
                                     // ™ž‘ ํ•˜€งŒ ช…‹œ ด€ ชปํ•œฉดด € œ‹ค.


Widget *pw = new SpecialWidget;
update(pw);

update(const_cast<SpecialWidget*>(pw));       // error!
                                              // const_cast<type>(expression) Š” 
                                              // ˜คง ƒˆ˜(constness)‚˜ €ˆ˜(volatileness)— ˜ํ–ฅ„ œ‹ค.
                                              // ดŸฐง ํ•˜ฉด ‹ค €Šฅํ•œ “ ‹ถณ  static_cast ™€ ฐจด€ —†Š” ฒƒ
                                              // ฐ™€ฐ ˜†˜ †ŒŠค ฒ˜Ÿ down cast€ ถˆ€Šฅํ•˜‹ค. 


œ„— ˜ˆ œ ด–ด„œ ƒฐ

  • dynamic_cast<type>(expression) ˜ˆ œ

~cpp 
Widget *pw
...
update( dynamic_cast<SpecialWidget*>(pw));    // ˜ณ‹ค. 
                                              // const_cast € down cast€ ถˆ€Šฅ ํ•œ Œ€‹ — dynamic_cast Š” งทธŒ€กœ
                                              // ํ•ด‹ €ชจ ฐฒด˜ ํฌธํ„— ž‹ ฐฒด€ €ฅดœ žˆœฉด ํ˜•€ํ™˜ด €Šฅํ•˜‹ค.
                                              // ถˆ€Šฅ ํ•˜ฉด null „ ฐ˜ํ™˜ํ•ดŠ” ธฐํŠํ•œ —ญํ• ด ํ•ต‹ฌด‹ค.

void updateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw)); // ˜ณ‹ค.
                                                 // reference—„œ„ ‚ฌšฉ €Šฅํ•˜‹ค? ทธŸ ถˆ€Šฅ ํ• ‹œ˜ ฒ˜ฆฌŠ”?
                                                 // ดŸด•ŒŠ” ˜ˆ™ธ(exception)„ ฐœƒ‹œœ €‹ค.

  • reinterpret_cast<type>(expression) € ฐจํ›„ ‹ค‹œ ฝ€’ค  •ฆฌํ•œ‹ค.

  • C —„œ €›ํ•˜€ •Š„ ฒฝšฐ ‹คŒ งคํฌกœ ‚ฌšฉํ•˜—ฌ

~cpp 
#define static_cast(TYPE, TEXPR)           ((TYPE) (EXPR))
#define const_cast(TYPE, TEXPR)            ((TYPE) (EXPR))
#define reinterpret_cast(TYPE, TEXPR)      ((TYPE) (EXPR))
ด ‡ฒŒ ตฌํ˜„ ํ•ด„œ Œ€„ํ•˜Š”ถ”ฒœํ•œ‹ค. (dynamic_cast Š” C˜  ˆฐจ  ํ”„กœทธž˜ฐ—„œ “žฅ ถˆ€)

~cpp 
    double result = static_cast(double, firstNumber)/ secondNumber;
    update(const_cast(SpecialWidget*, &sw));
    funcPtrArray[0] = reinterpret_cast(FuncPtr, &doSomething);

1.3. Item 3: Never treat arrays polymorphically

  • Item 3:  ˆŒ€กœ! ํดž˜Šค „˜ ‹คํ˜•„„ ํ†ตํ•œ ฐฐ—ด ทจธ‰„ ํ•˜€ ง

‹คฅธฐ ํ•„š” —†‹ค ด ˜ˆ œ ณดฉด •„ฐจ ‹ถ‹ค.
~cpp 
class BST { ... };
class BalancedBST : public BST { ... };
ดŸฐ ํดž˜Šค „ –ธํ–ˆ‹ค. ทธฆฌณ  ‹คŒ ฐ™€ ํ•จˆ˜กœ ํ•ด‹ ํดž˜Šค˜ ฐฐ—ด„ ‚ฌšฉํ•œ‹คณ  € •ํ•˜ž
~cpp 
void printBSTArray( ostream& s, const BST array[], int numElements)
{
    for ( int i = 0; i < numElements; ++i ){
        s << array[i]; 
    }
}
ทธฆฌณ  ‹คŒ ฐ™ด ‚ฌšฉํ•œ‹ค.
~cpp 
    BST BSTArray[10];
    ...
    printBSTArray(cout, BSTArray, 10);    // ˜ฌฐ”ฅดฒŒ ž‘™ํ•œ‹ค. •„ฌด ฌธ œ —†‹ค.

    //////////////////////////////////////

    BalancedBST bBSTArray[10];
    ...
    printBSTArray(cout, bBSTArray, 10);   // —ฐ ˜ฌฐ”ฅดฒŒ ž‘™ํ•˜Š”€?

œ„˜ ‘ฒˆงธ ํ˜ธถœ˜ ํดž˜Šค ƒ†˜ ‹คํ˜•  „งˆ„ ดšฉํ•œ ํ•จˆ˜ ดšฉ ฆ‰
~cpp 
   printBSTArray( cout, bBSTArray, 10 );
€  •ง ตœ•…˜ ฒฐ ถˆŸฌ “คธ‹ค.

C++—„œ˜ ฐฐ—ด€ arrayi ˜ ˜Š” *(array+i) ธฐ ดฒƒ˜ †Œ ถ” „ œ„ํ•ด„œ —„€ํžˆ ”ฐ€ฉด

*(array+ ( i *sizeof(an object in the array) )

กœ ‚ฌšฉํ•œ‹ค. Š‚Œด ˜คฒ €! ‹—ฐํžˆ ƒ†‹œ childŠ” parentณด‹ค ํฐ ฒฝšฐ€ ‹คฐ˜‚ฌดณ  ฐฐ—ด˜ œ„˜ ถ” ด —‰ง „ฐฝด ˜–ด „ฆฐ‹ค.

* ฐฒด˜ € ธ ‚ญ œ— €ํ•ด„œ„ •Œ•„ ณดฉด
~cpp 
    void deleteArray( ostream& logStream, BST array[])
    {
        logStream << "Deleting array at address " 
                  << static_cast<void*>(array) << '\n';
        delete [] array;
    }

    BalanceBST *balTreeArray = new BalancedBST[50];
    ...
    deleteArray(cout, balTreeArray);  // ดฒƒ —ญ‹œ  œŒ€กœ €›Œ€ฆฌ€ —†‹ค.
ž œ„™€ ฐ™ด ฐฒด˜ €›€„ ‹ด‹ํ•˜Š” ํ•จˆ˜ ž‘„ํ–ˆ„•Œ —ญ‹œ ฌธ œ€ žˆ‹ค.
~cpp 
    delete [] array
Š” ‹คŒ ฐ™€ ฝ”“œกœ ตฒด˜Š”ฒƒ ฐ™‹ค.
~cpp 
    for( int i = the number of elements in the array -1; i>0; --i)
    {
        array[i].BST::~BST();
    }
€ชจ ฐฒด˜ ํŒŒดดžงŒ €ฅด€กœ —ญ‹œ memory leak ํ˜„ƒ„ œํ‚จ‹ค.

1.4. Item 4: Avoid gratuitous default constructors.

  • Item 4: •”‹œ œกœ  œณต˜Š” ธฐณธ ƒ„ž ํ”ํ•˜. ํ˜€ ธฐณธ ƒ„ž˜ ชจํ˜ธ„„ ํŒŒ•…ํ•˜.

C++—„œ class templete งŒ“œŠ” ค‘ ƒ„ž œฉด compiler—„œ ธฐณธ ธ ƒ„ž งŒ“ค–ด ƒ„ํ•ด €‹ค. —ญ‹œ, ‹—ฐํžˆ ดˆธฐํ™”˜ ฌธ œ€ ฐœƒํ•  ฒƒด‹ค. —ฌธฐ—„œŠ” •ฝ„ ž„ธํ•œ €„„ –ธธ‰ํ•œ‹ค.

˜ˆ œ—„œ ‹œž‘ํ•˜ž
~cpp 
    class EquipmentPiece {
        public:
            EquipmentPiece(int IDNumber);
            ...
    }

ํ•ด‹ EquipmentPiece Š” ธฐณธ ƒ„ž€ €‹ค(?) ํ•˜‹ค. ดด ํฌฒŒ 3€€˜  œกœ „ช…ํ• ˆ˜ žˆ‹ค.

  • ฒซฒˆงธ ฌธ œŠ” ํ•ด‹ ํดž˜Šค ดšฉํ•˜—ฌ ฐฐ—ด„ ƒ„ ํ• •Œด‹ค. . ( The first is the creation of arrays )


~cpp 
    EquipmentPiece bestPieces[10];  
    EquipmentPiece bestPieces = new EquipmentPiece[10]; 
// ‘ฒฝšฐ ดˆธฐํ™” ํ•ด„ ฐฉ„€ —†–ด„œ —Ÿฌด‹ค.
ดด ‡ฒŒ ํ’€–ด ณดž
~cpp 
    int ID1, ID2, ID3, ... ID10;
    ...
    EquipmentPiece bestPiece[] = {
    EquipmentPiece(ID1),
    EquipmentPiece(ID2),
    EquipmentPiece(ID3),
    ...,
    EquipmentPiece(ID10),
}
ํ•˜€งŒ ดŸด ฒฝšฐ—Š” array heap arrays(heap˜—ญ ‚ฌšฉ arrayŠ” ˜กœ ฐ›•„“คž„)กœ˜ ํ™•žฅด ถˆ€Šฅํ•œ ณ  •œ ฐฉฒ•ด‹ค.

กฐธˆ ” ฐ˜ ธ ฐฉฒ•€ ‹คŒ ฐ™ด pointer ดšฉํ•œ  ‘„  œ‹œํ•œ‹ค.
~cpp 
    typedef EquipmentPiece* PEP;
    PEP bestPieces[10];
    PEP *bestPieces = new PEP[10];

    for ( int i = 0; i< 10; ++i)
        bestPiece[1] = new EquipmentPiece( ID Number );
ํ•˜€งŒ ดŸฌํ•œ ฐฉฒ•€ ํ•œˆˆ— ด„ ฌธ œ€ ˜ˆƒœ‹ค. ฐ”กœ deleteฌธ œ

‘€€ ตฌฒด œกœ ด•ธฐ ํ•ดณดฉด, ฒซฒˆงธกœ for ฌธ‹œ—„œ ํ• ‹˜Š” ฐฒด˜ ˆซž ธฐ–ตํ•˜ณ  žˆ–ด• ํ•œ‹ค. žƒ–ด„ฆฌฉด ฐจํ›„ resouce leakด ฐœƒ ํ• ฒƒด‹ค. ‘ฒˆงธกœŠ” pointer œ„ํ•œ ณต„ ํ• ‹œกœ ‹ค œ ํ•„š”ํ•œ memory šฉŸ‰ณด‹ค ” “ด‹ค.


ทธŸ ” ›ƒธฐŠ” ฐฉฒ•„  œ‹œํ•ด ณดž. (ด …„ ณดณ  žˆ…ธฉด, ด ‡ฒŒ„ “ธˆ˜ žˆ‹คž€ณด—ฌŠ”ฐ™‹ค.)
~cpp 
    void *rawMemory = operator new[](10*sizeof(EquipmentPiece));
    EquipmentPiece *bestPieces = static_cast<EquipmentPiece*>(rawMemory);
    for ( int i = 0; i< 10; ++i)
        new (bestPieces+1) EquipmentPiece ( ID Number );  // ดด placement new ณ  ํ•˜—ฌ Item 8 —„œ –ธธ‰ํ•œ‹ค. 
                                                          // ฒ˜Œ ณดณ  †€ž‹ค. –ด„œ ‚ฌธฐ• ํ•˜ฉด„œ --;;
                                                          // ด … ํŠธฐ‹ค. ’ค— „ช…ํ•˜‹ˆŒ ทธƒฅ „˜–ด€ ํ•˜Š”ฐ
                                                          // •”ํŠ ˜Š” ดํ•ด ฐˆฒƒด‹ค.
ฐธ € ฐ™€ ง“ ž˜ํ•ด †“Š”‹ค.

‹จ ํ™•ณดํ•œ ˜—ญ„ €šฐธฐŠ” ‰ฝ‹ค. ด ‡ฒŒ
~cpp 
    delete [] rawMemory;
—ญ‹œ‚˜ ดฒƒ„ delete— €ํ•œ ชจํ˜ธ„„  œณตํ•œ‹ค. ฌธ œ‹œ ˜Š”  € rawMemoryƒ— ฐฐ˜œ EquipmentPiece˜ destructor ํ˜ธถœ œ ฌดด‹ค. ˜ˆƒŒ€กœ destructor ฐ• œ ํ˜ธถœํ•ด ค˜• ํ•œ‹ค. ทธž˜„œ œ„€ •„‹ˆ, ดŸฐ‹˜ ‚ญ œ€ œ‹ค.
~cpp 
    for ( int i = 9; i>= 0; --i)
        bestPieces[i].~EquipmentPiece();    // –ธ œ‚˜ ŠŠ” €งŒ C++„ ฐฉข…„ € ธ‹ค „ˆ˜ žˆ‹ค.
    operator delete[](rawMemory);
ฐธณ กœ
~cpp 
    delete [] bestPieces; // ด ‡ฒŒ €šฐŠ”ด new operator€ “ค€ •Š•„„œ ถˆ€Šฅํ•˜‹ค.

  • ‘ฒˆงธ ฌธ œŠ” งŽ€ template class(ํŠํžˆ STL—„œ) “ค—ฒŒ •„ํ””„ •ˆฒจ€‹ค.
•„ž˜™€ ฐ™€ template class „ –ธํ–ˆ‹คณ  € •ํ•˜ฉด,
~cpp 
template<class T>
class Array{
public:
    Array(int size);
    ...
private:
    T *data;
};
template<class T>
Array<T>::Array(int size)
{
    data = new T[size];
    ....
}
ฒซฒˆงธ—„œ  œธฐœ ฌธ œ€ ดฒˆ—Š” template class ‚ด€—„œ –ด ‚˜ณ  žˆŠ” …ˆด‹ค. ฐธ •”‹ดํ•œ ฒฐ ดˆ€ํ•œ‹ค. ฌธ œŠ” ดŸฌํ•œ template class € ด œŠ” •„˜ˆ STLฐ™€ libraryกœ ตฌถ•˜—ˆ‹จ ‚ฌ‹ค. •Œ•„„œ ž˜ ธฐณธ ƒ„ž งŒ“ค–ด  šฉํ•˜‹œ. ‹คฅธ ฐฉ„ —†‹ค.

DeleteMe ด €„ด €‹คํ•˜‹ค ฐจํ›„ ณดฐ• ํ•„š”
  • „ฒˆงธ(งˆ€ง‰) ฌธ œŠ” virtual base class™€ ฐ™ด ธฐณธ ƒ„ž € ธ• ํ•˜‚˜ ง•„• ํ•˜‚˜ ฌ˜ํ•œ ”œ ˆงˆ˜ —ฐถœด‹ค.
ƒฐํ•ด ณด Virtual base class€ ™œ ธฐณธ ƒ„ž ํ•„š”กœ ํ•˜Š”€. ƒ„ž งŒ“ค–ด †“œฉด ƒ†ํ•˜Š” ดํ›„ ชจ“  ํดž˜Šค“ค—ฒŒ กœ“œ€ ฆฌŠ” …ˆด œ‹ค. ›ด ํ”“ค ค ชจ‘€ ˜ํ–ฅ„ ฐ›Š” ‚ฌํƒœด‹ค. งŒ•ฝ? ˆ˜งŒฐœ˜ ฐฒด ƒ„ดฉด ดต‰žฅํ•œ ฌธ œ€  ˆ˜ žˆ‹ค.


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:49
Processing time 0.0622 sec