C++ expedition template

What you will learn:

  • Template functions & template classes -> standard template classes
  • Friend functions & friend classes
  • Static data members & static member functions
  • Operator overloading: Anything is possible

A friend function

Function definition classification:

1. Global functions 2. Member functionsCopy the code

Friend global function

Example:

class Coordinate
{
	friend void printXY(Coordinate &c);
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
}
Copy the code

The keyword friend + declare friend functions (references or Pointers to objects)

  • Passing in references or Pointers is faster, and passing objects directly is not recommended.

Because we want to use printxy in our main function to call the private data member of the coordinate class. The premise is that we need to declare this function as a friend function in the coordinate class being called.

Friend member functions

A friend member function is defined in a class and declared as a friend function of another class.

class Coordinate
{
	friend void Circle::printXY(Coordinate &c);
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
}
Copy the code

PrintXY is not a global function. It is a member function of the Circle class. So now the Circle member function wants to use the private data of the Coordinate class, so we have to declare it in Coordinate.

class Circle
{
public:
	void printXY(Coordinate &c)
	{
		cout<< c.m_iX << c.m_iY; }}int main(a)
{
	Coordinate coor(3.5);
	Circle circle;
	circle.printXY(coor);
	return 0;
}
Copy the code

Risk of friend functions: breaking the encapsulation of Coordinate.

Friend function encoding implementation

Friend global function

2-2-FriendFunctionGlobal

Time.h

#ifndef TIME_H
#define TIME_H

#include <iostream>
using namespace std;

class Time
{
	friend void printTime(Time &t);/ / the key
public:
	Time(int hour,int min,int sec);

private:
	int m_iHour;
	int m_iMinute;
	int m_iSecond;

};
#endif
Copy the code

Time.cpp

#include "Time.h"

Time::Time(int hour, int min, int sec)
{
	m_iHour = hour;
	m_iMinute = min;
	m_iSecond = sec;
}
Copy the code

main.cpp

#include <iostream>
#include <stdlib.h>
#include "Time.h"
using namespace std;

void printTime(Time &t);
int main(a)
{
	Time t(6.34.35);
	printTime(t);
	system("pause");
	return 0;
}

void printTime(Time &t)
{
	cout << t.m_iHour << endl;
	// Time::m_iHour ": cannot access the private member (declared in the" Time "class)
	cout << t.m_iMinute << endl;
	cout << t.m_iSecond << endl;
}
Copy the code

As shown in the figure above, you can see that there are private data members that can access inside T.

Friend member functions

2-2-FriendMemberFunction

Time.h

#ifndef TIME_H
#define TIME_H
#include "Match.h"
#include <iostream>
using namespace std;

class Time
{
	friend void Match::printTime(Time &t);
	// Most important, suggestions are written on the outside. But it doesn't matter if you put it in public or private.
public:
	Time(int hour,int min,int sec);

private:
	int m_iHour;
	int m_iMinute;
	int m_iSecond;
};
#endif
Copy the code

Time.cpp

#include "Time.h"

Time::Time(int hour, int min, int sec)
{
	m_iHour = hour;
	m_iMinute = min;
	m_iSecond = sec;
}
Copy the code

Match.h

#ifndef MATCH_H
#define MATCH_H

class Time;// Declare such a class
class Match
{
public:
	void printTime(Time &t);//
};

#endif
Copy the code

Match.cpp

#include "Match.h"
#include "Time.h"
#include <iostream>

using namespace std;

void Match::printTime(Time &t)
{
	cout << t.m_iHour << ":" << t.m_iMinute << ":" << t.m_iSecond << endl;
}
Copy the code

main.cpp

#include <iostream>
#include <stdlib.h>
#include "Time.h"
#include "Match.h"
using namespace std;

int main(a)
{
	Time t(6.34.35);
	Match m;
	m.printTime(t);
	system("pause");
	return 0;
}
Copy the code

Friend void Match::printTime(Time &t); friend void Match::printTime(t); The method of Match can access it.

Because Match needs to access data inside Time, Match must declare the Time class :class Time;

Declarations of friend functions can be written in public, private, or global classes. But it is recommended to write it first.

Unit to consolidate

Define the Coordinate class and declare the global display function as the friend function of the Coordinate class data members m_iX and m_iY

The display function displays m_iX and m_iY

#include <iostream>
using namespace std;

/** * Define Coordinate class * friend functions: display * data members: m_iX, m_iY */
class Coordinate
{
    // Friend functions
    friend void display(Coordinate &coor);
public:
	Coordinate(int x, int y)
	{
		m_iX = x;
		m_iY = y;
	}
public:
	int m_iX;
	int m_iY;
};

/** * display is used to display m_iX, m_iY values */
void display(Coordinate &coor)
{
	cout << "m_iX:" << coor.m_iX << endl;
	cout << "m_iY:" << coor.m_iY << endl;
}

int main(void)
{
    // Instantiate the Coordinate object
	Coordinate coor(0.0);
    // Call display
    display(coor);
	return 0;
}
Copy the code

Friends metaclass

class Circle;// Declare the existence of the class

class Coordinate
{
	friend Circle;// Declare friends.
public:
	Coordinate(int x,int y)
private:
	int m_iX;
	int m_iY;
}
Copy the code
class Circle
{
public:
	void printXY(a)
	{
		cout << m_coor.m_iX << m_coor.m_iY;
	}
private:
	Coordinate m_coor; // Declare the object to use
}
Copy the code

Any Circle member function can use this object.

Precautions for friends

  • Friend relationships are not transitive (B is a friend of A, C is a friend of B,c is not necessarily a friend of A)
  • The unidirectionality of friendship. (One-way friendship)
  • The form and number of friend declarations are unlimited. (There is no upper limit on the number of friends, friends can be a mixture of classes and functions)

Friends are just a supplement to encapsulation (and, as a last resort, break encapsulation): directional exposure.

Friend class coding implementation

2-5-FriendClass

Time.h

#ifndef TIME_H
#define TIME_H

class Match;//
class Time
{
	friend Match;// Declare yourself a friend
public:
	Time(int hour,int min,int sec);

private:
	void printTime(a);
	int m_iHour;
	int m_iMinute;
	int m_iSecond;

};
#endif
Copy the code

Time.cpp

#include "Time.h"
#include <iostream>
using namespace std;

Time::Time(int hour, int min, int sec)
{
	m_iHour = hour;
	m_iMinute = min;
	m_iSecond = sec;
}
void Time::printTime()
{
	cout << m_iHour << "When" << m_iMinute << "Points" << "Seconds" << endl;
}
Copy the code

Match.h

#ifndef MATCH_H
#define MATCH_H

#include "Time.h"

class Match
{
public:
	Match(int hour,int min,int sec);
	void testTime(a);
private:
	Time m_tTimer; // Declare the existence of a friend
};

#endif
Copy the code

Match.cpp

#include "Match.h"
#include <iostream>

using namespace std;

Match::Match(int hour, int min, int sec):m_tTimer(hour, min, sec)
{

}
void Match::testTime()
{
	m_tTimer.printTime();
	cout << m_tTimer.m_iHour << ":" << m_tTimer.m_iMinute << ":" << m_tTimer.m_iSecond << endl;
}
Copy the code

main.cpp

#include <iostream>
#include <stdlib.h>
#include "Time.h"
#include "Match.h"
using namespace std;

int main(a)
{
	Match m(6.30.50);
	m.testTime();

	system("pause");
	return 0;
}
Copy the code

Because friends are declared in time.h

class Match;
friend Match;// Declare yourself a friend
Copy the code

Unit to consolidate

Constructor defines Watch class, data member: m_iHour, m_iMinute, m_iSecond Time is a friend of the Watch class.

Note: There are two ways to write friend classes, depending on the compiler.

1. friend classThe name of the class.
2. friendThe name of the class.Copy the code

If object A has object member B, and object B does not have A default constructor (that is, an argument is passed), then object A must initialize object B in the initializer list.

#include <iostream>
using namespace std;
class Watch;

/** * Define Time class * data members: m_iHour, m_iMinute, m_iSecond * Member functions: constructor * Friend class: Watch */
class Time
{
    / / the metaclass
    friend class Watch;
public:
	Time(int hour, int min, int sec)
	{
		m_iHour = hour;
		m_iMinute = min;
		m_iSecond = sec;
	}
public:
	int m_iHour;
	int m_iMinute;
	int m_iSecond;
};

/** * Defines the Watch class * data member: m_tTime * Member function: constructor * display to display the time */
class Watch
{
public:
	Watch(Time &t):m_tTime(t)
	{
	    
	}
	void display(a)
	{
		cout << m_tTime.m_iHour << endl;
		cout << m_tTime.m_iMinute << endl;
		cout << m_tTime.m_iSecond << endl;
	}
public:
	Time m_tTime;
};

int main(a)
{
	Time t(6.30.20);
	Watch w(t);
	w.display();

	return 0;
}
Copy the code

In the Watch constructor, we fill the data member m_tTime with a reference to Time.

  • The declaration of friends is not affected by access qualifiers and can be declared anywhere in the class.
  • Friends are unidirectional, A is A friend of B, and B is not necessarily A friend of A.
  • Friend functions and friend classes must be defined using the keyword friend.
  • Friends are not transitive

C + + static

It was introduced earlier:

  • Ordinary data members
  • Ordinary member functions
  • The const keyword
  • Constant data member & constant member function

Key words:

Static: Static data member & static member function

Here’s an example:

class Tank
{
public: Tank(){s_iCount++; } ~Tank(){s_iCount--; }static int getCount(a){ returns_iCount; }static int s_iCount;

private:
	string m_strCode;
	int Tank::s_iCount = 0; // Separate initialization of static data members
}
Copy the code

To become a static data member, you add the keyword static in front of what would otherwise be a normal data member. Similarly, a normal member function can be static by adding the keyword static in front of it.

In a tank battle, having more tanks on your side is heroic, having fewer tanks on your side is cowardly.

At this point we need all tank objects to know how many tanks they have.

  • Static data members exist independent of objects, dependent on classes, and so forth.
  • Static members exist without instantiation.
  • Cannot be instantiated in constructors; static data members must be initialized separately.

++ in constructor, ++ in destructor –; For each tank you can access this variable to know how many tanks you have left.

Two access methods:

  • Access static member functions directly through the class.
  • Object dot access mode.
int main(a)
{
	cout << Tank::getCount() <<endl;
	cout << Tank::s_iCount <<endl;

	Tank tank;
	cout << tank.getCount() <<endl;
	cout << tank.s_iCount << endl;

	return 0;
}

Copy the code

The difference between a static data member and a regular data member in memory.

Tank instantiates multiple objects, and the common data member codes are created one by one. Before these four objects are born, s_iCount is born, one and only.

  • Static member functions cannot call non-static member functions and non-static data members (they were born before objects existed).
  • Non-static member functions can call static member functions and static data members

The object (grandson) is not born, you are still a grandfather, can not use the grandson’s money.

Talking about static member functions from the this pointer.

class Tank
{
public:
	void fire(a);
	static int getCount(a);
private:
	string m_strCode;
	static int s_iCount;
}
Copy the code

When we call normal and static members with fire.

// Invisible this pointer
void fire(Tank *this)
{
	this -> m_strCode = "01";
	s_iCount = 0;
}

// Static member function. This pointer is not passed
static int getCount(a)
{
	m_strCode = "01"; 
	// The this pointer is not passed.
	// It is not clear which object is a member of,
	return s_iCount;
}
Copy the code

Matters needing attention

  • Static members must be initialized separately. (With classes, not with objects)
  • Static member functions cannot call non-static member functions and non-static data members
  • Non-static member functions can call static member functions and static data members
  • There is only one static data member and it exists independently of the object

Sizeof specifies the sizeof an object. It does not contain static data member sizes.

Static member function encoding

3-2-StaticMemberFunction

Tank.h

#ifndef TANK_H
#define TANK_H

class Tank
{
public:
	Tank(char code);
	~Tank();
	void fire(a);
	static int getCount(a);
private:
	static int s_iCount;
	char m_cCode;
};

#endif
Copy the code

Tank.cpp

#include <iostream>
#include "Tank.h"
using namespace std;

int Tank::s_iCount = 10; // outside of the constructor, initialized separately

Tank::Tank(char code)
{
	m_cCode = code;
	s_iCount++;
	cout << "tank" << endl;

}
Tank::~Tank()
{
	s_iCount--;
	cout << "~Tank()" << endl;
}

void Tank::fire()
{
	cout << "Tank--fire" << endl;
}
int Tank::getCount()
// Add static to the declaration, consistent with the common definition
{
	return s_iCount;
}
Copy the code

main.cpp

#include "Tank.h"
#include <stdlib.h>
#include <iostream>
using namespace std;

int main(a)
{
	cout << Tank::getCount() << endl;
	// Can be used before the class is instantiated
	Tank t1('A');
	cout << Tank::getCount() << endl;
	// The initial value of 10 becomes 11
	cout << t1.getCount() << endl;

	// instantiate self-managed memory on the heap
	Tank *p = new Tank('B');
	cout << Tank::getCount() << endl;
	Tank *q = new Tank('C');
	cout << q->getCount() << endl;

	delete p;
	delete q;

	cout << Tank::getCount() << endl;
	system("pause");
	return 0;
}
Copy the code

Running results:

Reminder 1: Can static member functions have the Const keyword?

static int getCount(a) const;

// Error: this pointer is const, now there is no pointer.
Static member functions do not allow modifiers
Copy the code

Call a static member function in a normal member function

void Tank::fire()
{
	getCount();
	cout << "Tank--fire" << endl;
}
Copy the code

Static member functions called from ordinary member functions can be called normally.

Call a normal member function in a static member function.

int Tank::getCount()
// Add static to the declaration. Definition time ordinary
{
	fire(); / / error
	m_cCode = 'C'; / / error
	// Error: invalid reference to non-static member "Tank::m_cCode
	return s_iCount;
}
Copy the code

An illegal call to a non-static member function

  • The static keyword is required to define both static member functions and static data members.
  • Public static member functions can be called directly by the class.
  • Static member functions can only access static data members and call static member functions.
  • Static data members cannot be initialized in constructors and must be initialized separately.

Unary operator overloading (key and Difficult)

Give new functionality to existing operators

The original + is to add numbers, overloading to string concatenation.

Here’s an example:

int main(a)
{
	string str1("mtian");
	string str2("yan");
	string str3 = str1 + "" + str2;
	cout << str3 <<endl;
	return 0; 
}
Copy the code

=, +, << are overloaded in the above code

int main(void)
{
	Coordinate coor1(1.3);
	Coordinate coor2(2.5);
	Coordinate coor3(0.0);
	coor3 = coor1 + coor2;
	cout << coor3 << endl;
	return 0;
}
Copy the code

=, +, << are overloaded in the above code. You can output coordinates directly.

Operator overloading nature: Function overloading

Defines the keyword operator for operator overloading

Unary operator overloading

  • Overloading of the minus sign
  • ++Overloading of symbols

Unary operator: Operates with only one operand.

Overloading of – (minus) :

  • Friend function overloading (class defines a friend function, global function)
  • Member function overloading

Member function overloading

class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate& operator- ();// Negative member function overload

private:
	int m_iX;
	int m_iY;
}

// Implementation: Invisible this pointer
Coordinate& Coordinate::operator- ()// Hidden parameters
{
	m_iX = -m_iX;
	m_iY = -m_iY;
	return *this;
}
Copy the code

When using

int main(a)
{
	Coordinate coor1(3.5);

	-coor1; //coor1.operator-();

	return 0;
}
Copy the code

Friend function overload

class Coordinate
{
friend Coordinate& operator-(Coordinate &coor); // Declare global functions with friends
public:
	Coordinate(int x,int y);
	Coordinate& operator- ();//

private:
	int m_iX;
	int m_iY;
}

/ / implementation

Coordinate& operator-(Coordinate &coor)
{
	coor.m_iX = -coor.m_iX;
	coor.m_iY = -coor.m_iY;

	return *this;
}

/ / call

int main(a)
{
	Coordinate coor1(3.5);

	-coor1; //operator-(cool);

	return 0;
}
Copy the code

Member function overloading is different from friend function overloading.

  • operator-(cool): friend function
  • coor1.operator-();: member function

Overloading of ++ symbols:

  • Pre –++Symbol overloading
  • The rear++Symbol overloading

++The operator is preloaded

class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate& operator+ + ();// Precedes the ++ & member function

private:
	int m_iX;
	int m_iY;
}

// Define the implementation

Coordinate& Coordinate::operator++()
{
	m_iX++;
	m_iY++;

	return *this;
}

/ / use

int main(a)
{
	Coordinate coor1(3.5);
	++coor1; //coor1.operator++()

	return 0;
}
Copy the code

Reload after ++

class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate operator+ + (int);/ / rear + +
	//1. The returned object is an object.
	//2. Pass the argument int. Int doesn't do anything. Just for identification.

private:
	int m_iX;
	int m_iY;
}


Coordinate operator+ + (int)
{
	Coordinate old(*this); // Save the original value
	m_iX++;
	m_iY++;

	return old;
}

int main(a)
{
	Coordinate coor1(3.5);
	coor1++; //coor1.operator(0);

	return 0;
}
Copy the code

Unary operator encoding implementation

4-2-UnaryOperatorOverload

  • Member function overloading

Coordinate.h

#ifndef COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate & operator- ();// Declare operator overloading
	int getX(a);
	int getY(a);
private:
	int m_iX;
	int m_iY;

};
#endif
Copy the code

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}

// Operator overload implementation
Coordinate &Coordinate::operator-()
{
	m_iX = -m_iX;
	this->m_iY = -this->m_iY;

	return *this;
}
Copy the code

main.cpp

#include "Coordinate.h"
#include <iostream>
#include <stdlib.h>
using namespace std;

int main(a)
{
	Coordinate coor1(1.3);
	cout << coor1.getX() << "," << coor1.getY() << endl;
	-coor1; //coor1.operator-()
	cout << coor1.getX() << "," << coor1.getY() << endl;
	system("pause");
	return 0;
}
Copy the code

Running results:

  • Friend function operator overloading

4-2-UnaryOperatorOverloadByFriendFunction

Coordinate.h:

class Coordinate
{
	friend Coordinate &operator-(Coordinate &c); // Declare friend function operator overloading

public:
	Coordinate(int x,int y);
	int getX(a);
	int getY(a);
private:
	int m_iX;
	int m_iY;
};
Copy the code

Coordinate.cpp:

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}
// Operator overload implementation
Coordinate &operator-(Coordinate &c)
{
	c.m_iX = -c.m_iX;
	c.m_iY = -c.m_iY;

	return c;
}
Copy the code

Main.cpp, no change.

The results are unchanged.

Unary operator encoding implements two (++ operator overloading)

4-3-PlusPlusOperatorOverload

Coordinate.h

#ifndef COORDINATE_H
#define COORDINATE_H
#include <iostream>
using namespace std;

class Coordinate
{
	friend Coordinate &operator-(Coordinate &c);

public:
	Coordinate(int x,int y);
	Coordinate &operator+ + ();/ / front + +
	Coordinate operator+ + (int);// ++,int = ++ Instead of returning a reference, return an object.

	int getX(a);
	int getY(a);
private:
	int m_iX;
	int m_iY;

};

#endif
Copy the code

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}
Coordinate &operator-(Coordinate &c)
{
	c.m_iX = -c.m_iX;
	c.m_iY = -c.m_iY;

	return c;
}
Coordinate &Coordinate::operator++()
{
	m_iX++;
	m_iY++;
	return *this;
}
Coordinate Coordinate::operator+ + (int)
{
	Coordinate old(*this);
	this->m_iX++;
	this->m_iY++;
	return old;
}
Copy the code

main.cpp

#include "Coordinate.h"
#include <iostream>
#include <stdlib.h>
using namespace std;

int main(a)
{
	Coordinate coor1(1.3);
	cout << coor1.getX() << "," << coor1.getY() << endl;
	++coor1;
	cout << coor1.getX() << "," << coor1.getY() << endl;
	-coor1; //coor1.operator-()
	cout << coor1.getX() << "," << coor1.getY() << endl;
	cout << (coor1++).getX() << ",";
	cout << (coor1++).getY() << endl;
	cout << coor1.getX() << "," << coor1.getY() << endl;
	// So coor1++ executes twice.
	// By the time the last line was printed, x and y were already multiplied by 2.
	system("pause");
	return 0;
}
Copy the code

Binary operator overloading

  • +Number operator overload: friend function overload & member function overload

+Member function overloading

class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate operator+ (const Coordinate &coor); // Member functions

private:
	int m_iX;
	int m_iY;
}


Coordinate operator+ (const Coordinate &coor)
{
	Coordinate temp;
	temp.m_iX = this ->m_iX + coor.m_iX;
	temp.m_iY = this ->m_iY + coor.m_iY;

	return temp;
}

int main(a)
{
	Coordinate coor1(3.5);
	Coordinate coor1(4.7);
	Coordinate coor1(0.0);

	coor3 = coor1 + coor2; // coor1.operator+(coor2); operator+(coor1,coor2)

	return 0; 
}
Copy the code

Friend function overloading of the plus operator

class Coordinate
{
friend Coordinate operator+ (const Coordinate &c1, const Coordinate &c2);
public:
	Coordinate(int x,int y);

private:
	int m_iX;
	int m_iY;
}

// const limits addition not to modify the value of the addend itself

Coordinate operator+ (const Coordinate &c1, const Coordinate &c2)
{
	Coordinate temp;
	temp.m_iX = c1.m_iX + c2.m_iX;
	temp.m_iY = c1.m_iY + c2.m_iY;

	return temp;
}

int main(a)
{
	Coordinate coor1(3.5);
	Coordinate coor1(4.7);
	Coordinate coor1(0.0);

	coor3 = coor1 + coor2; Call operator+(coor1,coor2)

	return 0; 
}

Copy the code

overloading<<Output operator

class Coordinate
{
friend ostream& operator <<(ostream &out,const Coordinate &coor);
// The return value must be ostream&
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
}

/ / implementation

ostream& operator<<(ostream &out,const Coordinate &coor)
{
	out << coor.m_iX <<","<<coor.m_iY;

	return out;
}

/ / use

int main(a)
{
	Coordinate coor(3.5);
	cout <<coor; //operator<<(cout,coor);

	return 0;
}
Copy the code

Understand that cout is an ostream object.

Can the output operator take member function overloading?

  • Using the plus operator overload: Pass in a parameter (the second addend), the first addend defaults to the current object.
  • The first object must be ostream, not the current pointer object.

[]Index operator overload

class Coordinate
{
public:
	Coordinate(int x,int y);
	int operator[] (int index); // Member functions
private:
	int m_iX;
	int m_iY;
}

int Coordinate::operator[] (int index)
{
	if(0==index)
		{returnm_iX; }if(1==index)
		{return m_iY;}
}

/ / use
int main(a)
{
	Coordinate coor[3.5];
	cout << coor[0]; // coor.operator[](0);
	cout << coor[1]; // coor.operator[](1);

	return 0;
}
Copy the code

Can index operators use friend function overloading?

Friend function overloading cannot be used. The first argument to a friend function can be a this pointer or something else: the index operator, however, must have a this pointer to point to an object.

Binary operator code example

4-5-BinaryOperatorOverload

Overloading of operators: For plus operators, output operators, index operators.

Coordinate.h

#ifndef COORDINATE_H
#define COORDINATE_H
#include 
       
        // contains ostream
       
using namespace std;

class Coordinate
{
	friend Coordinate &operator-(Coordinate &c);
	friend Coordinate operator+(Coordinate c1,Coordinate c2);
	friend ostream &operator<<(ostream &output, Coordinate &coor);
public:
	Coordinate(int x,int y);
	Coordinate &operator+ + ();/ / front + +
	Coordinate operator+ + (int);/ / rear + +
	//Coordinate operator+(Coordinate &c); // Member functions overload the plus sign
	// There are two arguments.
	int operator[] (int index);
	int getX(a);
	int getY(a);
private:
	int m_iX;
	int m_iY;

};
#endif
Copy the code

Coordinate.cpp

#include "Coordinate.h"

Coordinate::Coordinate(int x, int y)
{
	m_iX = x;
	m_iY = y;
}

int Coordinate::getX()
{
	return m_iX;
}

int Coordinate::getY()
{
	return m_iY;
}
Coordinate &operator-(Coordinate &c)
{
	c.m_iX = -c.m_iX;
	c.m_iY = -c.m_iY;

	return c;
}
Coordinate &Coordinate::operator++()
{
	m_iX++;
	m_iY++;
	return *this;
}
Coordinate Coordinate::operator+ + (int)
{
	Coordinate old(*this);
	this->m_iX++;
	this->m_iY++;
	return old;
}

//Coordinate Coordinate::operator+(Coordinate &c)
/ / {
//	Coordinate temp(0, 0);
//	temp.m_iX = this->m_iX +c.m_iX;
//	temp.m_iY = this->m_iY +c.m_iY;
//
//	return temp;
/ /}
Coordinate operator+(Coordinate c1, Coordinate c2)
{
	Coordinate temp(0.0);
	temp.m_iX = c1.m_iX + c2.m_iX;
	temp.m_iY = c1.m_iY + c2.m_iY;

	return temp;
}

ostream &operator<<(ostream &output, Coordinate &coor)
{
	output << coor.m_iX << "," << coor.m_iY;
	return output;
}
int Coordinate::operator[] (int index)
{
	if (0 == index)
	{
		return m_iX;
	}if (1 == index)
	{
		returnm_iY; }}Copy the code

main.cpp

#include "Coordinate.h"
#include <iostream>
#include <stdlib.h>
using namespace std;

int main(a)
{
	Coordinate coor1(1.3);
	Coordinate coor2(2.4);
	Coordinate coor3(0.0);

	coor3 = coor1 + coor2;

	//cout << coor3.getX() << "," << coor3.getY() << endl;

	cout << coor3[0] < <endl;
	cout << coor3[1] < <endl;
	

	system("pause");
	return 0;
}
Copy the code

  • Operator overloading can give operators new functionality.
  • Operator overloading uses the keyword operator
  • Some operators must use member function overloading, while others must use friend function overloading.

Friend function overloading cannot be used if the index operator is overloaded, because the index operator’s first argument must be passed this. The output operator << can only be overloaded with friend functions (because the output first argument is ostream).

  • ++ operator overloading needs to distinguish between pre-overloading and post-overloading.

Unit to consolidate

Define Coordinate class data members: m_iX, m_iY Member functions: constructor overload the “–” operator, overload the “+” operator

#include <iostream>
using namespace std;

/** * Define Coordinate class * data members: m_iX, m_iY * Member functions: constructor * overload -- operator, overload + operator */
class Coordinate
{
public:
    Coordinate(int x, int y)
	{
		m_iX = x;
		m_iY = y;
	}
    // prefix -- operator overload
	Coordinate & operator--()
    {
        this ->m_iX--;
        this ->m_iY--;
        return *this;
    }
    
    
    // after -- operator overload
    Coordinate operator--(int)
    {
        Coordinate old = *this;
        this ->m_iX--;
        this ->m_iY--;
        return old;
    }
    
    
    
    // The + operator is overloaded
	Coordinate operator+(Coordinate c)
    {
        Coordinate temp(0.0);
        temp.m_iX = this ->m_iX + c.m_iX;
        temp.m_iY = this ->m_iY + c.m_iY;
        return temp;
    }
    
    

public:
	int m_iX;
	int m_iY;
};

int main(void)
{
	Coordinate coor1(1.3);
	Coordinate coor2(2.4);
	Coordinate coor3(0.0);

	coor1--;
	--coor2;
	coor3 = coor1 + coor2;

	cout << coor3.m_iX << endl;
	cout << coor3.m_iY << endl;

	return 0;
}
Copy the code

Running results:

A function template

Why use templates?

// Compare two integers
int max(int a,int b)
{
	return(a>b)? a:b; }// Compare two floating point numbers
float max(float a,float b)
{
	return(a>b)? a:b; }// Compare two strings
char max(char a,char b)
{
	return(a>b)? a:b; }Copy the code

Three different types, but the logic is exactly the same.

Solution:

The type is passed in as a parameter. The computer is going to do these three functions.

Keyword: Template typename class

Class is not a class, but a data type.

template <class T> // Declare a parameter typeT max(T a.T b// Function template {
	return(a>b)? a:b; }// If you do not specify, the computer will automatically recognize it
int ival = max(100.99); // The template function

char cval = max<char> ('A'.'B');
// When specified, the parameter must be of this type
Copy the code

Function templates are templates that produce template functions. With function templates, the computer does not generate code data; Real code is generated only when it is used

template <typename T>
void swap(T& a,T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}

int x =20,y=30;
swap<int>(x,y);
Copy the code

Variables as template parameters

template <int size>
void display(a)
{
	cout << size <<endl;
}

display<10> ();Copy the code

Multi-parameter function template

template <typename T,typename C>
void display(T a,C b)
{
	cout << a <<"" <<b <<endl;
}

/ / use
int a = 1024; string str = "helloworld";
display<int.string>(a,str);
Copy the code

Typename and class can be mixed

template <typename T,class U>
T minus(T* a.U b)

template <typename T,int size>
void display(T a)
{
	for(int i=0; i < size; i++)cout << a << endl;
}

display<int.5> (15);
Copy the code

Function templates and overloading

Function templates can make an infinite number of template functions.

Overloading occurs between template functions.

Template functions created by different function templates can also be overloaded, as in the following example:

template <typename T>
void display(T a);

template <typename T>
void display(T a,T b);// Different number of parameters

template <typenameT,int size>
void display(T a);

display<int> (10);
display<int> (10.20);
display<int.5> (30);// Three functions form overloads
Copy the code
  • Function templates themselves do not generate code in memory, because without template parameters there is no way to know what function to compose

  • Template arguments can be types, variables (which are actually constants at compile time), or combinations of types and variables

  • Different template functions of the same function template can be regarded as mutually overloading

  • Template functions from different function templates with the same function name but different template or function parameters can also be overloaded

Function template code practices

5-2-FunctionTemplate

main.cpp

#include <iostream>
#include <stdlib.h>
using namespace std;

template <typename T>
void display(T a)
{
	cout << a << endl;
}

template <typename T, class S>
void display(T t.S s)
{
	cout << t << endl;
	cout << s << endl;
}

template <typename T,int Ksize>
// This variable becomes constant when instantiated

void display(T a)
{
	for (int i = 0; i < Ksize; i++)
	{
		cout << a << endl; }}int main(a)
{
	display<int> (10);
	display<double> (10.98); // The template function
	display<int.double> (5.8.3);
	display<int.3> (10);
	system("pause");
	return 0;
}
Copy the code

  • A function template can have one or more arguments.
  • There is no need to use a function template if it has zero parameters.
  • When using a function template, you need to specify template parameters. In this case, the function is called a template function.
  • You can use a function template to define multiple functions with the same function and different data types.

Unit to consolidate

Defines a function template that swaps the positions of two numbers

5-4-swapNum

#include <iostream>
using namespace std;
#include <stdlib.h>
/** * swapNum */ swapNum */
template <typename T>
void swapNum(T &a, T &b)
{
	T temp = a;
	a = b;
	b = temp;
}

int main(void)
{
	float x = 10.1;
	float y = 20.5;
	// Call the template function
	swapNum<float>(x, y);
	cout << "x = " << x << endl;
	cout << "y = " << y << endl;
	system("pause");
	return 0;
}
Copy the code

Class template

template <class T>
class MyArray
{
public:
	void display(a)
	{... }private:
	T *m_pArr;
}
Copy the code

Except for the data type, everything else is basically the same.

To define a member function outside the class, we need to do something like this:

template <class T> // This line precedes each out-of-class member function defined. // Class name <T>void MyArray<T>::display()
{

}

/ / use
int main(a)
{
	MyArray<int> arr;
	arr.display();

	return 0;
}
Copy the code

Class template

Usage of multiple arguments to a class template

template <template T,int KSize>
class Container
{
public:
	void display(a);
private:
	T m_obj;
}

// Out-of-class definition
template<typename T,int KSize>
void Container<T,KSize>::display()
{
	for (int i = 0; i < KSize; ++i)
	{
		cout << m_obj << endl; }}int main(a)
{
	Container<int.10> ct1;
	ct1.display();

	return 0;
}
Copy the code

Special reminder:

Template code cannot be compiled separately (class declarations and definitions are written in.h files).

  • A class template is defined outside the class and is preceded by each member functiontemplate<typename T, int KSize>

Class template encoding implementation

5-6-ClassTemplate

MyArray.h:

#ifndef MYARRAY_H
#define MYARRAY_H

#include <iostream>
using namespace std;

template <typename T,int Ksize,int KVal>// Template parameter list
class MyArray
{
public:
	MyArray();
	~MyArray()
	{
		delete[]m_pArr;
		m_pArr = NULL;
	}// Functions written inside classes need no attention.
	void display(a);

private:
	T *m_pArr;
};
template <typename T, int KSize, int KVal>
MyArray<T, KSize, KVal>::MyArray()
{
	m_pArr = new T[KSize];
	for (int i = 0; i < KSize; i++) { m_pArr[i] = KVal; }}template <typename T,int KSize,int KVal>
void MyArray<T, KSize, KVal>::display()
{
	for (int i = 0; i < KSize; i++)
	{
		cout << m_pArr[i] << endl; }}#endif
Copy the code

MyArray.cpp

// Write nothing
Copy the code

main.cpp:

#include <stdlib.h>
#include <string>
#include "MyArray.h"
using namespace std;

int main(a)
{
	MyArray<int.5.6> arr;// The template class has been formed
	arr.display();
	system("pause");
	return 0;
}
Copy the code

Running results:

  • Defining a class template is equivalent to defining a series of classes of the same type with different functions
  • The keyword template is used to define a class template
  • Template parameters can be either types or variables
  • The parameters that define the class template can be typename and class, and can be used interchangeably

Unit to consolidate

Defines a rectangle class template that contains member functions that calculate the area and perimeter of a rectangle. The members are length and width.

#include <iostream>
using namespace std;

/** * Define a rectangular class template Rect * member functions: calcArea(), calePerimeter() * data members: m_length, m_height */
template <typename T>
class Rect
{
public:
    Rect(T length,T height);
    T calcArea(a);
    T calePerimeter(a);
public:
	T m_length;
	T m_height;
};

/** * Class attribute assignment */
template <typename T>
Rect<T>::Rect(T length,T height)
{
	m_length = length;
	m_height = height;
}

/** * the area method implements */
template <typename T>
T Rect<T>::calcArea()
{
	return m_length * m_height;
}

/** * the perimeter method implements */
template <typename T>
T Rect<T>::calePerimeter()
{
	return ( m_length + m_height) * 2;
}

int main(void)
{
	Rect<int> rect(3.6);
	cout << rect.calcArea() << endl;
	cout << rect.calePerimeter() << endl;
	return 0;
}
Copy the code

Matters needing attention:

template <typename T>
Rect<T>::Rect(T length,T height)//
      
        is applied to classes instead of methods.
      
Copy the code

Standard template library

STL: Standard Template Lib

A standard template library is a collection of templates that the system has already written that you can use (instantiate)

Common parts:

Vector (Vecotr)

The essence of a vector is to encapsulate an array; Automatically lengthen or shorten depending on the number of stored elements.

Excellent features: Random reads can be completed in constant time

We initialize a vector:

vector<T> v1; // vector holds objects of type T. The default constructor v1 is null
vector<T> v2(v1); //v2 is a copy of v1
vector<T> v3(n, i); //v3 contains n main elements
vector<T> v4(n); //v4 contains n copies of initialized elements with values

// Specific usage
vector<int> ivec1;
vector<int> ivec2(ivec1);

vector<string> svec1;
vector<string> svec2(svec1);

vector<int> ivec4(10.- 1); // The array contains 10 -1's
vector<string> ivec4(10."hi"); // The array contains 10 hi's
Copy the code

The above codes are:

Initialize an empty vector to initialize another vector with one vector

Vector uses the following functions:

methods role
empty () Check whether the vector is empty
begin() Returns the first element of a vector iterator
end () Returns the next element at the end of the vector iterator
clear () Empty vector
front () Number one
back () One last piece of data
size () Gets the data size in the vector
push_back (elem) Insert data into the tail of the vector
pop_ back() Delete vector tail data

After vector initialization, we have to have matching functions to make us feel convenient, and these are all matching functions of vectors.

Examples in practical use are as follows:

int main(a)
{
	vector<int> vec; // Pass the argument int
	vec.push_back(10);// Insert element 10 at the end
	vec.push_pop();/ / remove 10
	cout << vec.size()<<endl;// This is still 0
	return 0;
}

// Array traversal
for(int k=0; k < vec.size(); k++) {cout << vec[k] << endl;
}

Copy the code

Iterator traverses.

int main(a)
{
	vector vec;
	vec.push_back("hello"); // Insert a lot of elements at the end
	vector<string>::iterator citer = vec.begin(); // Define a vector iterator
	// <> specifies the data type used by the vector. :: Identifies the current iterator as an iterator belonging to a vector
	// Iterator citer data type: 'Vector 
      
       ::iterator citer'
      
	// This iterator refers to the first element of the current vector.

	for(; citer ! = vec.end(); citer++)// Stop condition: end refers to the position next to the last vector of the current vector vec.
	// points to the next element.
	{
		cout << *citer << endl; // Add * to indicate the element value.}}Copy the code

The list: a list

The schematic diagram is as follows:

  • The linked list will have a header. Each linked list consists of a number of nodes.
  • None of the nodes is called an empty list
  • There are multiple nodes. The first node is called a header.
  • For each node there are two parts. Part is the data part (ABCDE are all data fields), and part is the pointer part.
  • The pointer part is used to concatenate nodes.

Double-linked lists: Can be found from the beginning to the end, and can be found from the end to the head.

Insert data between D and E, so d points to the new data, and the new data points to E.

Features: Fast data insertion speed (unlike vector, insert one other all have to move back)

The use method is basically the same as array.

Map: the map

Key – value mapping one – to – one, find values by key.

map<int.string> m;// Define a mapping object by mapping
pair<int.string> p1(10."shanghai");// Put key&Value into the map
pair<int.string> p2(20."beijing");

m.insert(p1); // Put the pair into m
m.insert(p2);

cout << m[10] < <endl;// Access values by key
cout << m[20] < <endl;
Copy the code
map<string.string> m;// Define a mapping object by mapping
pair<string.string> p1("S"."shanghai");// Put key&Value into the map
pair<string.string> p2("B"."beijing");

m.insert(p1);// Put the pair into m
m.insert(p2);

cout << m["S"] < <endl;// Access values by key
cout << m["B"] < <endl;
Copy the code

Standard template library code implementation

Vector uses the following methods:

6-2-vectorPushBackPopFor

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <list>
#include <map>
using namespace std;

int main(a)
{
    vector<int> vec;
    
    vec.push_back(3);// Insert from the tail
    vec.push_back(4);
    vec.push_back(6);
    
    vec.pop_back();// remove one from the tail
    
    for (int i=0; i<vec.size(); i++) {cout << vec[i] << endl;
    }
    cout << "end for" << endl;
    cout << vec.size() << endl;
    return 0;
}
Copy the code

Running results:

Iterator version: 6-2-2-2 -IteratorVector

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <list>
#include <map>
using namespace std;

int main(a)
{
    vector<int> vec;
    
    vec.push_back(3);// Insert from the tail
    vec.push_back(4);
    vec.push_back(6);
    
    / / the iterator
    vector<int>::iterator itor = vec.begin();
    
    //cout << *itor << endl; // Print out the first element value
    
    for(; itor ! = vec.end(); itor++) {cout << *itor << endl;
    }
    cout << "end iterator" << endl;
    cout << vec.front() << endl;// The first element
    cout << vec.back() << endl;// The last element
    
    return 0;
}
Copy the code

Running results:

Notice that end gets the position next to the last element

Standard template library coding implementation 2

List traversal code:

6-3-ListOnlyCanUseIterator

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <list>
#include <map>
using namespace std;

int main(a)
{
	list<int> list1;
	list1.push_back(4);
	list1.push_back(7);
	list1.push_back(10);

// for (int i=0; i
// 	{
// cout << list1[i] << endl; / / error

/ /}
	return 0;
}

Copy the code

Error:

Type 'list<int>' does not provide a subscript operator

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <list>
#include <map>
using namespace std;

int main(a)
{
	list<int> list1;
	list1.push_back(4);
	list1.push_back(7);
	list1.push_back(10);

// for (int i=0; i
// 	{
// cout << list1[i] << endl; / / error

/ /}
  list<int>::iterator itor = list1.begin();
	for(; itor ! = list1.end(); itor++) {cout << *itor << endl;
	}
	return 0;
}
Copy the code

The map through:

6-3-MapIterator

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <list>
#include <map>
#include <string>
using namespace std;

int main(a)
{
	map<int.string> m;
	pair<int.string> p1(3."hello");
	pair<int.string> p2(6."world");
	
	//m.push_back(p1); Pushback is not a member of map
	
	m.insert(p1);
	m.insert(p2);

	cout << m[3] < <endl;
	cout << m[6] < <endl;

	map<int.string>::iterator itor = m.begin();
	for(; itor ! = m.end(); itor++) {//cout << *itor << endl; // Error, each containing keyValue
		cout << itor->first << endl;
		cout << itor->second << endl;
	}
	
	return 0;
}

Copy the code

Running results:

String type map

6-3-2-StringMap

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <list>
#include <map>
#include <string>
using namespace std;

int main(a)
{
	map<string.string> m;
	pair<string.string> p1("H"."hello");
	pair<string.string> p2("W"."world");
	//m.push_back(p1); / / error
	m.insert(p1);
	m.insert(p2);

	cout << m["H"] < <endl;
	cout << m["W"] < <endl;

	map<string.string>::iterator itor = m.begin();
	for(; itor ! = m.end(); itor++) {//cout << *itor << endl; // Error, each containing keyValue
		cout << itor->first << endl; / / output key
		cout << itor->second << endl;/ / output value
	}
	
	return 0;
}
Copy the code

Running results:

  • A vector is a wrapper around an array, so once an object is instantiated, its size can change. The size can vary depending on the number of elements
  • List is characterized by fast data insertion.
  • Map can be used together with pair to store multiple key-value pairs.
  • Different vendors of standard template library implementation details can be different, the basic usage and principle of the same.

Unit to consolidate

Use vector to store the numbers 3, 6,8, and 4 and iterate over them. Use map to store S-Shang Hai B-bei Jing G-Guang Zhou and traverse it

6-5-VectorMapIterator

#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std;

int main(void)
{
    // Use vector to store numbers: 3, 4, 8, 4
    vector<int> vec;
    vec.push_back(3);
    vec.push_back(4);
    vec.push_back(8);
    vec.push_back(4);
    // Cycle to print numbers
    
    vector<int>::iterator itor1 = vec.begin();
    for(; itor1 ! = vec.end(); itor1++) {cout << *itor1 <<endl;
    }
    
    // Use map to store string key-value pairs
    map<string.string> m;
    pair<string.string> p1("S"."Shang Hai");
    pair<string.string> p2("B"."Bei Jing");
    pair<string.string> p3("G"."Guang Zhou");
    m.insert(p1);
    m.insert(p2);
    m.insert(p3);
    // Prints map data
    map<string.string>::iterator itor2 = m.begin();
    for(; itor2 ! = m.end(); itor2++) {cout << itor2->first <<endl;
        cout << itor2->second <<endl;
    }
    return 0;
}
Copy the code

Running results:

Matters needing attention:

 cout << itor2->first <<endl;
 cout << itor2->second <<endl;
Copy the code

Itor1 and ITor2 cannot have the same name.