C++08 (Classes and Objects)

Posted by sunnypal on Sat, 20 Jun 2020 03:39:27 +0200

Classes and Objects

Differences between 0.C/C++.

C language: a process-oriented language
C Language: Computer Language
The drawback of C is that it separates attributes from behavior in design

  1. What is the purpose and meaning of computer language design?
    Solve real-world problems with computers (simulate reality)
  2. What simulates reality?
    Structures - Entity Properties, Functions - Behaviors
  3. What's in reality is called an entity--described by attributes and behaviors
    C++: Object-Oriented Language

Classes and Objects:

  1. oop thought

0.1.C Language Structures

C Language Structures

typedef struct Data
{
	int ma;
	int mb;
}DATA;
void SetValue(DATA* pdt,int a,int b)  //assignment
{
	pdt->ma=a;
	pdt->mb=b;
}
int main()
{
	DATA val;
	setValue(&val,10,20);
	return 0;
}

0.2 Linking variables to functions

Connect variables with functions-->Function pointers

typedef struct Data
{
	int ma;
	int mb;
	void(*func)(struct Data*, int, int);
}DATA;
//void (*) (struct Data*,int,int);
void SetValue(DATA* pdt, int a, int b)
{
	pdt->ma = a;
	pdt->mb = b;
}
int main()
{
	DATA val;
	val.func = &SetValue;
	val.func(&val, 10, 20);  //Entity execution behavior can be understood
	//val.func(10,20);
	return 0;
}

1. Classes and Objects

1.1 oop Thought (Thought of Object-Oriented Language)

1.2 Write a human

//class Class Identification  
class People
{
public:
	void eat(char* what)
	{
		std::cout << mname << " is eatting " << what << std::endl;
	}
	void sleep(char* _where)
	{
		std::cout << mname << " is sleepping  at" << _where << std::endl;
	}
	void play()
	{
		std::cout << mname << " is playing  doudou!" << std::endl;
	}
private:
	char mname[10];//Full name
	bool msex;//Gender
	int mage;//Age
};
/*
	Set point until end of class or next access qualifier  
*/
/*
	Class default access qualifier 
		private:
*/
int main()
{
	//int a; //type generates variable 
	People p1;//People Type Class Type Type Instantiation Object
	//Access qualifier, access failure
	//strcpy_s(p1.mname, strlen("xiaoming"), "xiaoming");
	p1.eat("meat");
	return 0;
}

Three Features of 2.C++.

Three main features of C++:
Encapsulate Inheritance Polymorphism

Access Qualifier
From the set point until the end of the class or the next access qualifier, the default is private
1.public: arbitrary access
2.protected: in subclasses and classes of this class
3.private: in this class

2.1 Packaging (should be visible to you, should not be invisible to you)

Encapsulation is the protection of attributes and behaviors

The process should be: Ask for money, OK, and then Xiao Ming takes the money from his pocket and passes it to me
Attributes are private and need to be protected
Behavior is public,

Designing a student class

#include<iostream>
class Student
{
private:
	char name[10];
	bool sex;
	int age;
public:
	void learn(const char* what)//
	{
		std::cout << name << "learning" << what << std::endl;
	}
	void eat(const char* when, const char* what)
	{
		std::cout << name << "eating" << what << "on" << when << std::endl;
	}
	void sleep(const char* when, const char* what)
	{
		std::cout << name << "sleeping at" << what << "on" << when << std::endl;
	}
};

2.2. Membership variables and membership methods -- relationships with objects?

3.this


The statement that this pointer points to an object is too biased. This pointer points to the space occupied by the object (no resources)

The this pointer does not allow modifications and does not change (its stored address cannot change)

3.1 thiscall calling convention

Member Method Call Dependent Object Call

4. Default functions in classes

If not provided by the designer, six default functions are provided
1. Constructors
2. Destructors
3. Copy Constructor
4. Overloaded functions of assignment operators
5. Overloaded functions to take address operators
6. const-modified overloaded functions for address fetching operators

Initialization and destruction of classes in 4.1.C

Class initialization function:

Destroy function for class:

Main function call

Constructors and Destructors in 4.2C++.

4.2.1 Constructor

The function of the constructor:
Initialize the memory space occupied by the object (give the object the memory space resources)
Constructor (can be overloaded, make a difference)
There is a this pointer (if not, there is no way to determine which member variable to initialize)
It cannot be called artificially, it can only be called by the system (the constructor is thiscall call, depends on object call, the constructor is not completed, the object is not generated)
Constructor not completed: Object incomplete --->Semi-finished object

Steps to generate objects

  1. Open up the memory space occupied by the object <-----System provided
  2. Invoke Constructor (Memory Space Initialized Object)<----System Provided
    What is the object?
    Space + Resources
    What is a variable?
    space
    What is the difference between definition and instantiation?
    Definition--->Space (Exploration)
    Instantiation --> Space + Resources (Exploit + Give Resources)
    What should the system-provided constructors look like?
    90 lines are ambiguous, 91 lines are the call to the default constructor

4.2.2 Destructor

Destructor (can't overload,'death is the same')
Role of destructors:
Release other resources occupied by objects
Destructor (can't overload,'death is the same')
Has this pointer
Can be called artificially

Realization:
Delete[] mname------>Destroy open content on the heap

Call time:
Destruction of objects:
1. Call destructors (release other resources occupied by objects)
2. The system releases the space occupied by the object--->the contents on the stack

4.2.2 Differences between constructors and destructors

1. The function of the constructor:
Initialize the memory space occupied by the object (give the object the memory space resources)
Constructor (can be overloaded, make a difference)
There is a this pointer (if not, there is no way to determine which member variable to initialize)
It cannot be called artificially, it can only be called by the system (the constructor is thiscall call, depends on object call, the constructor is not completed, the object is not generated)
2. The role of destructors:
Release other resources occupied by objects
Destructor (can't overload,'death is the same')
Has this pointer
It can be called artificially, but it degenerates into a normal function call, which is called again when the program is finished.
3. Differences:
Attributes that are naturally assigned are not modifiable and cannot be invoked artificially.
The process of extinction can be manipulated artificially.
4. Order of constructors and destructors:
Construct before destruct
Opening up space is in the stack, 1 goes into the stack then 23 goes into the stack, stack is first in then out, so when destroyed, 3 goes out of the stack first.

Exercise 4.2.3: C++ Encapsulated Chain List (Friendly Relationships)

Friendship:
1. Unidirectionality

#include<iostream>

class CLink;  //forward declaration
class Node //Node Class
{
public:
	Node(int data = 0);//Give a default value
private: //Data protection cannot be completed if private ownership is changed to public ownership
	int mdata;
	Node* next;
	friend class CLink;
};
Node::Node(int data)//Scope preceded by function name--"means that a function is a member method of a class
{
	mdata = data;
	next = NULL;
}

class CLink    //Chain List Class--"Set of Nodes
{
public:
	CLink();
	~CLink();
	//Head plug, end plug, delete print
	void InsertOfHead(int val);
	void InsertOfTail(int val);

	bool Empty();
	bool DeleteOfHead();//To determine if it is empty
	bool DeleteOfTail();

	void Print();

private:
	Node* phead;
};
CLink::CLink()
{
	phead = new Node();  //Head Pointer Points to Head Node
}
CLink::~CLink()
{
	//Release Head Node and Data Node
	Node* p = phead;
	Node* tmp;
	while (p != NULL)
	{
		tmp = p->next;
		delete p;
		p = tmp;
	}
	phead = NULL;
}
void CLink::InsertOfHead(int val)
{
	Node* s = new Node(val);
	s->next = phead->next;
	phead->next = s;
}
void CLink::InsertOfTail(int val)
{
	Node* s = new Node(val);
	Node* tail = phead;
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	tail->next = s;
}

bool CLink::Empty()
{
	//Is the pointer field of the header node empty
	return phead->next == NULL;
}
bool CLink::DeleteOfHead()
{
	if (Empty())
	{
		return false;
	}
	Node* q = phead->next;
	phead->next = q->next;
	delete q;
}
bool CLink::DeleteOfTail()
{
	if (Empty())
	{
		return false;
	}
	//Delete the last node, the last previous pointer should point to empty
	Node* tail0 = phead;//Second Last Node
	Node* tail = tail0->next;//Last Node
	while (tail->next != NULL)
	{
		tail0 = tail0->next;
		tail = tail0->next;
	}
	tail0->next = NULL;
	delete tail;
	return true;

}

void CLink::Print()
{
	Node* p = phead->next;
	while (p!= NULL)
	{
		std::cout << p->mdata << " ";
		p = p->next;
	}
	std::cout << std::endl;
}
int main()
{
	CLink cl;
	for (int i = 0; i < 5; ++i)
	{
		cl.InsertOfHead(i + 1);
	}
	cl.Print();
	for (int i = 0; i < 5; ++i)
	{
		cl.InsertOfTail(i + 1);
	}
	cl.Print();
	cl.DeleteOfHead();
	cl.Print();
	cl.DeleteOfTail();
	cl.Print();

	return 0;
}

4.3 Copy Constructor

Generate new objects of the same type with an existing object
Must use reference when parameter to prevent recursive call to copy constructor

class CGoods
{
public:
	CGoods()
	{
	}
	CGoods(int amount)
	{
		mamount = amount;
	}
	CGoods(char* name, float price, int amount)
	{
		mname = new char[strlen(name) + 1]();
		strcpy_s(mname, strlen(name) + 1, name);
		mprice = price;
		mamount = amount;
	}
	//deep copy
	CGoods(const CGoods& rhs)
	{
		mname = new char[strlen(rhs.mname) + 1]();
		strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);
		mprice = rhs.mprice;
		mamount = rhs.mamount;
	}

	/*
	1. Prevent formal parameters from modifying the value of an argument
	2. Receive Implicitly Generated Temporary Quantity----"Must Receive Temporary Quantity with Common Reference (Constant)
	*/
	//void  CGoods&  
	void operator=(const CGoods& rhs)//this: Left Operand Parameter: Right Operand
	{
		if (this == &rhs)//self assigning
		{
			return;
		}
		delete[] mname;
		mname = new char[strlen(rhs.mname) + 1]();
		strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);
		mprice = rhs.mprice;
		mamount = rhs.mamount;
	}

	~CGoods()
	{
		delete[] mname;
		mname = NULL;
	}
private:
	char* mname;
	float mprice;
	int mamount;
};

int main()
{
	CGoods good1("Bread", 4.5, 100);

	CGoods good2 = good1;----->copy constructor

	CGoods good2("milk", 2.5, 1000);

	good2 = good1;//The compiler assigns values through overloaded functions of the -"assignment operator --->operator, as detailed in 4.4


	return 0;
}

4.3.1 Copy Constructor

copy constructor

4.3.2 Shallow Copy Constructor

Default copy constructor: shallow copy (consider implementing deep copy if member variables have pointers)
Pointing to the same memory area, when good2 is destroyed, mname memory is freed, and when good1 is destroyed, a duplicate release error occurs.

4.3.3 Why the parameter of a copy constructor must be a reference&

Copy Constructor If the parameter is not referenced, recursive calls generate the parameter object, resulting in stack overflow and program crash

4.4. Overloaded functions of assignment operators (shallow copies, to implement their own deep copies)

Assign an existing object to an existing object of the same type
Steps to construct:
1. Determine whether it is an assignment
2. Release old resources
3. Opening up new resources
4. Assignment

4.4.1 Questions frequently asked in interviews

4.4.1.1. Differences between class and struct

The default access qualifiers are different:

   class:
        private
   struct:
	     public

4.4.1.2. What is the size of an empty structure and why?What about empty classes?

C: (Memory blocks are carved out with a module, an empty structure is equivalent to a non-existent module, and memory blocks cannot be carved)
An empty structure cannot be defined

C++:
1 byte
Structures are handled as class types

Empty class:
1

Classes simulate Abstract concepts, which are abstracted from entities. Entities exist in reality. Therefore, C++ designers set the size of empty classes to 1 by default, and spatial objects can simulate entities.

struct Data
{
public:
	void Show()
	{
		std::cout << "hello world" << std::endl;
	}
};

//Only member methods without member variables are considered empty classes
class Test
{
public:
	void Show()//_thiscall 
	{
		std::cout << "hello world!" << std::endl;
	}
};

int main()
{
	Test test;//Object that does not exist for test if 0
	test.Show();
	//Data val;
	//val.Show();
	//std::cout << sizeof(struct Data) << std::endl;
	return 0;
}

4.4.1.3. Return value type of assignment operator

class CGoods
{
public:
	CGoods()
	{
		mname = new char[1]();
	}
	CGoods(char* name, float price, int amount)
		:mname(new char[strlen(name) + 1]()),
		mprice(price),
		mamount(amount)
	{
		strcpy_s(mname, strlen(name) + 1, name);
	}
	CGoods(const CGoods& rhs)
	{
		mname = new char[strlen(rhs.mname) + 1]();
		strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);

		mprice = rhs.mprice;
		mamount = rhs.mamount;
	}
	CGoods& operator=(const CGoods& rhs)
	{
		if (this != &rhs)
		{
			delete[] mname;
			mname = new char[strlen(rhs.mname) + 1]();
			strcpy_s(mname, strlen(rhs.mname) + 1, rhs.mname);

			mprice = rhs.mprice;
			mamount = rhs.mamount;
		}
		return *this;
	}
	~CGoods()
	{
		delete[] mname;
		mname = NULL;
	}
private:
	char* mname;
	float mprice;
	int mamount;
};
int main()
{
	int a = 10;
	int b = 20;
	int c;
	c = a = b;//continuous assignment

	CGoods good1("Bread", 4.5, 100);
	CGoods good2("Milk bread", 4.5, 100);

	CGoods good3;
	good3 = good2 = good1;
	//Good2 = good1; //good2 itself 
	return 0;
}

4.5. Overloaded functions to take address operators

4.6. const-modified overloaded functions for address fetching operators

5. Temporary Objects

Temporary object:
Lifetime: End of expression, encounter semicolon, end of life cycle

5.1 Optimization of Temporary Objects

Optimization of temporary objects:

5.2 Classification of Temporary Objects

  1. Explicitly generate temporary objects:
    Specify exactly what temporary objects are generated
  2. Implicitly generate temporary objects:
    What temporary objects should compiler presentations generate
    80 rows are implicitly generated and 82 rows are explicitly generated (type only, no object name, explicit generation)

5.3 Properties of Temporary Quantity

  1. Built-in Type---"Constant
  2. Custom Type----"Variable
  3. Implicitly Generated Temporary Object----"Constant

5.4 References improve the lifetime of temporary objects

References increase the lifetime of temporary objects the same as reference variables
95 lines of code: assigns the address of the temporary object to the pointer, which points to an invalid object when the temporary object is destroyed after the statement ends

6. Life cycle of the object

CGoods ggood1("g1", 4, 10);//.data
static CGoods ggood2("g2", 2, 10);//.data---"Destroy after the entire program ends

int main()
{
	CGoods lgood1;//stack  
	CGoods lgood2("l2", 10, 20);//stack  
	static CGoods lgood3("l3", 30, 10);//.data---"Destroy after the entire program ends

	CGoods lgood4 = CGoods("l4", 40, 10);//stack  
	CGoods lgood5 = 20;//stack (optimized generation, only lgood5 objects generated)
	
	lgood1 = CGoods("tmp", 20, 30);---->Not to generate new objects, all not optimized, expression completes temporary destruction, constructs, assignments, destructive calls
	lgood2 = 30;
	lgood3 = (CGoods)(10,20,30,40);//Strong comma expression {}

	/*
		comma expression  
			The data ends up with the last one
	*/

	CGoods* pc1 = new CGoods("pc1", 10, 20);//heap  
	CGoods* pc2 = new CGoods[2];//Heap has two object builds

	CGoods* pc3 = &CGoods("pc3", 10, 20);


	CGoods& rc3 = CGoods("rc3", 10, 20);

	delete pc1;
	delete[] pc2;
	return 0;
}
CGoods ggood3("g3", 3, 10);//.data

7. Class type return values: are brought out through temporary objects

Return value in:
1.<=4 eax
2. >4 && <=8 eax edx
3. >8 Temporary Volume

How many temporary quantities are generated?
A: five return value objects when test1, test2, arg, tmp, return.

class Test
{
public:
	Test(int a = 0)
	{
		ma = a;
	}
	Test(const Test& rhs)
	{
		ma = rhs.ma;
	}
	~Test()
	{
		std::cout << "Test::~Test()" << std::endl;
	}
private:
	int ma;
};

Test getObject(Test arg)
{
	Test tmp = arg;
	//...
	return tmp;
}
int main()
{
	Test test1(20);
	Test test2;

	test2 = getObject(test1);
	return 0;
}


class Test
{
public:
	Test(int a = 0)
	{
		std::cout << "Test::Test(int)" << std::endl;
		ma = a;
	}
	Test(const Test& rhs)
	{
		std::cout << "Test::Test(const Test&)" << std::endl;
		ma = rhs.ma;
	}
	void operator=(const Test& rhs)
	{
		std::cout << "Test::operator=(const Test&)" << std::endl;
		if (this == &rhs)
		{
			return;
		}
		ma = rhs.ma;
	}
	~Test()
	{
		std::cout << "Test::~Test()" << std::endl;
	}
private:
	int ma;
};
/*
	Custom type as parameter  
		References are typically set to references (references do not generate objects, one less construct and one less destruct) 
		Efficiency Improvement
*/
Test getObject(Test& rhs)--->Reference does not generate
{
	Test tmp = rhs;//2
	//...
	return tmp;//An object was returned  
}
int main()
{
	Test test1(10);//1
	Test rt = getObject(test1);//3---"return value passed in, resulting in optimization, generating rt only
	return 0;
}

Initialization list of 7.1 constructors


8.Use of const and static to modify class members

8.1 const modifier

  1. Modify member variables: must initialize
  2. Modifying member methods: common methods

A normal object cannot call a normal method, but a normal object can only call a normal method (a common method risks modifying the value of a constant variable)
Common objects can call common methods

Normal member methods cannot be called in normal methods
Common methods can be called in normal member methods

class Test
{
public:
	Test(int a) : ma(a)
	{}
	void Show()const  //const Test* const this;
	{
		std::cout << "ma:" << ma << std::endl;
	}
	void Print()
	{
		Show();
		std::cout << "hello world!" << std::endl;
	}
private:
	int ma;
};
int main()
{
	Test test(10);//Constant Object 
	test.Show();
	return 0;
}

8.2 Interview Question: Briefly describe const

1. Variables: C/C++.
2. Modification request processing is not allowed
3.const modifies member variables

8.3 static modifier member

1. Modify member variables:
Initialization: member variables are not objects, belong to classes (which are shared by all objects), and must be initialized outside the class
Access: Not dependent on Object Access
2. Modifying member methods:
_cdecl cannot access normal member variables without this pointer
Access only: global variable static member variable
Access: Not dependent on Object Access

Static member methods cannot call normal member methods
Normal member methods can call static member methods
Memory space occupied by constructor initialization object
Static member variables do not belong to objects, so constructors cannot initialize static member variables

class Test
{
public:
	Test(int b)
		: mb(b)
	{}
	static void Show()//cdecl does not have this pointer  
	{
		//Print();
		std::cout << "ma:" << ma << std::endl;
		//std::cout << "mb:" << mb << std::endl;
	}
	void Print()//thiscall
	{
		std::cout << "mb:" << mb << std::endl;
		Show();
	}

	static int ma;
private:
	int mb;
};
int Test::ma = 10;
int main()
{
	Test test1(10);
	Test test2(20);

	std::cout << test1.ma << std::endl;
	std::cout << Test::ma << std::endl;//
	test1.Show();
	Test::Show();
	test1.Print();
	return 0;
}

8.4 Function pointer calls function method at call point

//int (*) (int,int) 
int Sum(int a, int b)
{
	std::cout << "::Sum(int,int)" << std::endl;
	return a + b;
}

class Test
{
public:
	Test(int a)
		:ma(a)
	{}
	void Show()
	{
		std::cout << "ma:" << ma << std::endl;
	}
private:
	int ma;
};

/*
	void (*) (); //Test::
*/
/*
	.*  ->*
	When a function pointer points to a class member method
*/
int main()
{
	int(*Func) (int, int);
	Func = &Sum;
	(*Func)(10, 20);
	//Sum(10, 20);

	Test test(10); ------>Dependent Object Call
	void(Test::* cppfunc)() = &Test::Show;
	(test.*cppfunc)();
	Test* ptest = new Test(20);
	(ptest->*cppfunc)();
	return 0;
}

8.5 Exercises

class String
{
public:
	//NULL
	String(char* ptr)
	{
		assert(ptr!=NULL);
		if(ptr==NULL)
		{
			return;
		}
		mptr = new char[strlen(ptr) + 1]();
		strcpy_s(mptr, strlen(ptr) + 1, ptr);
	}
	String(const String& rhs)
	{
		mptr = new char[strlen(rhs.mptr) + 1]();
		strcpy_s(mptr, strlen(rhs.mptr) + 1, rhs.mptr);
	}
	String& operator=(const String& rhs)
	{
		if (this == &rhs)
		{
			return *this;   //---->Left Operand
		}
		delete[] mptr;
		mptr = new char[strlen(rhs.mptr) + 1]();
		strcpy_s(mptr, strlen(rhs.mptr) + 1, rhs.mptr);
		return *this;
	}
	~String()
	{
		delete[] mptr;
		mptr = NULL;
	}
private:
	char* mptr;//
};

int main()
{
	String str("hello");
	String str2 = str;
	str2 = str;
	return 0;
}

9. Single Case Mode

Design Mode 
	Singleton mode
	Class can only produce one object
 1. Screen the interface of the generated object
	Place the constructor in private
 2. Provide interfaces to generate unique objects
	1. cannot be returned in the form of a class type
	2.static 

9.1 Design a headmaster class (single case mode: lazy mode)

/*
	An interface is designed to generate objects 
		static is usually written out
*/
class Rector
{
public:
	static Rector* getInstance(char* name, int age, bool sex)//----"Get Instances
	{
		if (pre == NULL)
		{
			pre = new Rector(name, age, sex);
		}
		return pre;
	}
private:
	Rector(char* name, int age, bool sex)
	{
		mname = new char[strlen(name) + 1]();
		strcpy_s(mname, strlen(name) + 1, name);
		mage = age;
		msex = sex;
	}

	char* mname;
	int mage;
	bool msex;

	static Rector* pre;//Identifies that the unique object does not belong to the scope of the entire class
};
Rector* Rector::pre = NULL;

int main()
{
	Rector * pr1 = Rector::getInstance("zhangsan", 45, true);
	Rector * pr2 = Rector::getInstance("zhangsan", 45, true);
	Rector * pr3 = Rector::getInstance("zhangsan", 45, true);



	//Rector re1("zhangsan", 45, true);
	//Rector re2("lisi", 45, true);
	return 0;
}

9.1.1 Singleton Pattern Generates Class What is the Function Value Return Class

&, * both because no temporary object is generated (generating a temporary object results in two objects, and the singleton pattern is unique)
Both constructors and copy constructors can generate objects, so not only should construction be considered, but also copy construction, so 9.1 code is not perfect

9.2 Abstract Principal Class into Model (Thread Security)

9.1 Unlocked

1. Unlocked Conditions: Unsafe Factors

9.2 Locking

2. After unlocking, the first time the security is guaranteed, but the second time the third time the unlock still needs to be unlocked, resulting in resource consumption

9.3 Double Lock

3. Face Resource Consumption: Double Lock Single Case Mechanism

9.4 Hungry Man Mode: Greedy Loading

Threads are an execution path for a process

Processing in threads generates unique objects--->Unsafe
Generate Unique Object Before Thread Opens---"Security

class SingleTon
{
public:
	static SingleTon* getInstance()  //Generate an interface
	{
		return psing;
	}
private:
	SingleTon()
	{}
	SingleTon(const SingleTon&);
	static SingleTon* psing;//.data
};
SingleTon* SingleTon::psing = new SingleTon();//Before main executes

int main()
{
	SingleTon* psingle1 = SingleTon::getInstance();
	SingleTon* psingle2 = SingleTon::getInstance();
	SingleTon* psingle3 = SingleTon::getInstance();
	return 0;
}

9.5 Lazy Mode: Delayed Loading

class SingleTon
{
public:
	static SingleTon* getInstance()
	{
		if (psing == NULL)//Thread Security Second and Later  
		{
			lock();
			if (psing == NULL)
			{
				psing = new SingleTon();
			}
			unlock();
		}
		return psing;
	}
private:
	SingleTon()
	{
	}
	SingleTon(const SingleTon&);
	static SingleTon* psing;
};
SingleTon* SingleTon::psing = NULL;

int main()
{
	SingleTon* psingle1 = SingleTon::getInstance();
	SingleTon* psingle2 = SingleTon::getInstance();
	SingleTon* psingle3 = SingleTon::getInstance();
	return 0;
}

Topics: C less