128-C ++ Estudio Sexto

class Int
{
    
    
private:
	int value;
public:
	Int(int x=0):value(x){
    
    }
	~Int(){
    
    }
	int &Value(){
    
    return value;}
	const int&Value()const{
    
    return value;}
};

class Object
{
    
    
	int num;
	Int*pInt;
public:
	Object(int x=0):num(x),pInt(new Int(x+10)){
    
    }
	~Object()
	{
    
    
		if(pInt!=nullptr)
		{
    
    
			delete pInt;
		}
		pInt=nullptr;
	}
	int GetNum(){
    
     return num;}

	Int&GetInt(){
    
     return *pInt;}

	Int*GetPInt(){
    
    return pInt;}

};


int main()
{
    
    
	Object Obj(10);

	Int*p=Obj.GetPInt();

	Int x=Obj.GetInt();

	return 0;
}

Cuando nuestra función principal se está ejecutando, se abre un marco de pila para la función principal y se define un objeto Obj. Los miembros de este objeto son: num y pInt, num = 10, puntero pInt nuevo un espacio Int (4 bytes) x +10 = 20, toma 20 para inicializar este espacio. New here tiene dos acciones: solicitar espacio y tomar el constructor de Int para construir un objeto (inicializar 20), y dar la dirección del objeto construido a pInt
Int * p = Obj.GetPInt (); Dar el contenido de pInt a p, p El puntero apunta al objeto 20.
Int x = Obj.GetInt (); devuelve el objeto al que apunta y asigna la copia del objeto ax
Inserte la descripción de la imagen aquí

Obj.GetPInt()->Value()=100;

De acuerdo con la relación de llamada de la función, se transfiere de izquierda a derecha. Obj.GetPInt () llama a la función GetPInt () para devolver el puntero PInt de tipo Int. Value () es el método para apuntar al objeto. 100 es el valor valor, que en realidad es PInt. Asignar valor al objeto puntiagudo, 20 se convierte en 100

Pregunta:
Si no hay & antes de GetInt ()

Int GetInt(){
    
     return *pInt;}

¿Se pueden ejecutar las siguientes tres oraciones?

Int x=Obj.GetInt();//可以
int a=Obj.GetInt().Value();//可以
Obj.GetInt().Value()=100;//没必要

Cuando movilizamos la función GetInt (), abriremos un marco de pila para esta función, le daremos el puntero this y devolveremos el objeto * pInt. Necesitamos movilizar el constructor de copia para usar el objeto temporal como una transición (temporal objeto). Construido en el área de la pila de funciones principal), asigne este objeto temporal ax, por lo que la primera línea de código es correcta. En la segunda línea de código, la devolución anterior también es un valor muerto, y el valor del valor muerto se saca a A. La segunda línea de código es correcta. Pero la tercera línea de código es cambiar el valor del valor muerto. Una vez que el cambio no tiene sentido, este valor se destruye rápidamente y no se puede asignar el valor muerto.

Agregue & delante de GetInt (), está bien

Int&GetInt(){
    
     return *pInt;}

Lo que se devuelve es el objeto al que apunta pInt. 100 cambios son los objetos apuntados por pInt en Obj

En C ++, puede sobrecargar * overload ->

Int& operator*() {
    
     return *pInt; }
const Int& operator*() const {
    
     return *pInt; }

Int* operator->() 
	{
    
     
		return pInt;  
		//return &**this; 两种写法都可以 
	}

Int & operator * () {return * pInt;}
Sobrecarga *, devuelve lo que pInt se refiere a
const Int & operator * () const {return * pInt;} Este es un método regular y devuelve a qué se refiere pInt. mantener la coherencia, también se ha devuelto en forma de const Int &,

int main()
{
    
    
	Object obj(10);
	Int a = *obj;
	int x = (*obj).Value();
	(*obj).Value() = 100;

	return 0;
}

Ahora es equivalente a la función dando un nuevo nombre, sobrecargando para entender la referencia para
ver el programa: se define un objeto obj, su num = 10, y el puntero pInt apunta a un objeto Int. El constructor construye un objeto de tipo Int con un valor de 20, * obj es equivalente a movilizar su propia sobrecarga de operador, desreferenciar y devolver directamente el objeto apuntado a a, (* obj) .Value (), dando 20 ax, (* obj) .Value () = 100; convirtiendo 20 en 100
Esta sobrecarga * es muy similar a los punteros
Inserte la descripción de la imagen aquí

Sobre la sobrecarga ->

Inserte la descripción de la imagen aquí
esto apunta a obj, este es el objeto en sí, * * esta movilización apunta a sobrecarga, y devuelve el alias del objeto apuntado por pInt, y devuelve la dirección de este objeto

int main()
{
    
    
	Object obj(10);
	obj->Value();
	obj.operator->()->Value();
	return 0;
}

obj. es el método del objeto en sí
obj-> está sobrecargado ->, el objeto devuelto es un objeto de tipo Int, return (* Int), -> primero se combina con el objeto en sí y devuelve el tipo de la punta objeto, también Eso es (* Int), luego (* Int) -> Valor (); De hecho, este lugar -> funciona dos veces. Solo necesita escribir un -> para
sobrecargar * y ->, este tipo se llama puntero inteligente

Sobrecarga()

Functor

class Add_Int
{
    
    
private:
	int value;
public:
	Add_Int(int x = 0) :value(x) {
    
    }
	~Add_Int() {
    
    }
public:
	//int operator()(Add_Int * const this,int x,int y)
	inline int operator()(int x, int y)
	{
    
    
		value = x + y;
		return value;
	}
};
int main()
{
    
    
	Add_Int add;
	int x = add(10, 20);//重载()
	int y = add.operator()(10, 20);//解析
	//  y = operator()(&add,10,20);		//正确
	//  y = operator(&add)(10,20);		//错误,因为这里的()是函数名
	x = Add_Int(0)(12, 23);//类型名后面加()意味着构建对象,拿对象调动()重载

}

Solo hay functores unarios y binarios en la biblioteca estándar

class Stack
{
    
    
private:
	double data[10000000];//超过内存,崩溃
	int maxsize;
	int pos;
public:
	Stack() {
    
     pos = -1; }
	~Stack() {
    
    }

	int size()const {
    
     return pos + 1; }
	int empty() const {
    
     return size() == 0; }
	int full() const {
    
     return size() == maxsize; }
	void push(double x)
	{
    
    
		pos += 1;
		data[pos] = x;
	}
	// pop
	double Top() {
    
     return data[pos]; }
	void  pop() {
    
     pos -= 1; }
};

int main()	  //主函数栈区大小 vs 1M // Liunx // 10M
{
    
    
	Stack st;//开辟在局部变量区
	return 0;
}

El método anterior no es bueno, el tipo no es conveniente para convertir y no está satisfecho con el usuario

Tipo de plantilla

template<typename Type>//Type是标识符
class Stack
{
    
    
	Type* data;
	int maxsize;
	int pos;
public:
	Stack(int sz = 10)
	{
    
    
		maxsize = sz;
		pos = -1;
		data = new Type[maxsize];  //???
		// 1 // 2;
		//cout << typeid(Type).name() << endl;
		//打印出int, double, student 
		//typeid(Type).name x;//错误 
		//     string
	}
	~Stack()
	{
    
    
		maxsize = 0;
		pos = -1;
		delete[]data;
		data = nullptr;
	}
	int size() const {
    
    
		return pos + 1;
	}
	bool empty() const {
    
    
		return size() == 0;
	}
	bool full() const {
    
    
		return size() == maxsize;
	}
	void push(const Type& x)
	{
    
    
		if (!full())
		{
    
    
			pos += 1;
			data[pos] = x;
		}
	}
	Type& top() {
    
    
		return data[pos];
	}
	const Type& top() const {
    
    
		return data[pos];
	}
	void pop() {
    
    
		pos -= 1;
	}
};

? ¿Por qué son estas tres secciones siguientes más const?
Inserte la descripción de la imagen aquí
Podríamos definir una pila común Stack;
también es posible definir una pila recurrente const Stack;
los objetos ordinarios pueden movilizar el método ordinario, el método también puede movilizar el
sujeto a menudo a menudo solo para movilizar el método a menudo
escribir más El grado de reutilización de este código

desde la perspectiva de todo el diseño tipográfico

Inserte la descripción de la imagen aquí
Uno es el método normal, el valor no se puede cambiar, el
otro es el método normal, el valor se puede cambiar

¿Cómo se usa este método de pila?

int main()
{
    
    
	Stack<int> ist(100);
	Stack<double> dst;
	Stack<Student> sst;
	///ist = dst;
	return 0;
}

Al compilar, el compilador encuentra que ha definido una pila de tipos de plantilla y ha puesto la pila de tipos de plantilla compilada en la tabla de descripción. Al compilar la función principal, encuentra el int dado y genera un fragmento de código.
Inserte la descripción de la imagen aquí
Luego, vea el doble y genere un fragmento de código.
Inserte la descripción de la imagen aquí
Luego vea el estudiante y genere un fragmento de código. La
Inserte la descripción de la imagen aquí
clase de plantilla es el tipo del tipo generado.
Inserte la descripción de la imagen aquí
Tenga en cuenta que este proceso se determina en el momento de la compilación.
Asegúrese de especificar las tres partes de código en <>
Inserte la descripción de la imagen aquí
Después de la compilación, se forma el archivo obj y el enlace se convierte en un archivo ejecutable. La
plantilla es el código que genera el código (compilador)

Solo en la plantilla, cuando se llama a este método, participa en la compilación. Este método no se moviliza y el compilador no puede verificar si hay un problema con este método.

Los tipos de pila son diferentes y no se pueden asignar entre sí. Los tipos no coinciden. Una vez completada la compilación, el nombre del tipo cambia. El tipo es Stack <int> y el tipo es Stack <double>.

Siguiente para resolver este problema
Inserte la descripción de la imagen aquí

class Object
{
    
    
private:
	int value;
public:
	Object(int x = 0) :value(x)
	{
    
    
		cout << "construct object: " << this << endl;
	}
	~Object()
	{
    
    
		cout << "deconstruct object: " << this << endl;
	}
};

int main()
{
    
    
	Stack<Object> ost;
	cout << ost.empty() << endl;
	return 0;
}

Definir una pila vacía
Inserte la descripción de la imagen aquí
Lógicamente hablando, es una pila vacía, vacía es verdadera

int main()
{
    
    
	Stack<Object> ost;
	cout << ost.size() << endl;
	return 0;
}

Inserte la descripción de la imagen aquí

Apila 0, pero al construir, se construyen 10 objetos, la diferencia lógica y física

STL

clase de cuerda


#include<string>
#include<iostream>
using namespace std;
int main()
{
    
    
	string s1("yhpinghello");
	string s2 = "yhping";

	string s3; 

	s3 = s1 + s2;
	s3 = s1 + "yhping";
	s3 = "yhping" + s1;
	s3 = "hello" + "yhping";//错误,这个不可行,常性字符串,没有+
	
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;

	return 0;
}
int main()
{
    
    
	string s1("yhping");  
	string s2("yhx");

	cout << (s1 < s2) << endl;//比较
	s1.append("hello");//尾部接
	cout << s1 << endl;

	int len = s1.size();//大小
	int cap = s1.capacity();//容量一定大于字符串的个数
	for (int i = 0; i < len; ++i)
	{
    
    
		cout << s1[i] << " ";//下标访问
	}
	//s1[10] = 'x';//改变字符串内容 可以检查越界
	cout << s1 << endl;
	const char* s = s1.c_str();//返回s1字符串的地址
	return 0;
}

vector

Equivalente a matriz expandible

#include<vector>
#include<iostream>
using namespace std;
int main()
{
    
    
	vector<int> iar = {
    
     12,23,34,45,56,67,78 };//可以直接初始化 
	vector<double> dar;
	//vector<Student> sar;要什么添加什么,vector就操作什么 

	int n = iar.size();//个数 
	for (int i = 0; i < n; ++i)
	{
    
    
		cout << iar[i] << " ";//打印 
	}
	iar.push_back(100);//尾部添加数据,但是没有头部添加的方法 
	
	int a = iar.back();//返回最后一个元素 
	int x = iar.front();//返回第一个元素 

	iar.clear();//清空
	return 0;
}

Iterador

//迭代器,面向对象版本的指针 
int main()
{
    
    
	vector<int> iar = {
    
     12,23,34,56,67,78 };

	vector<int>::iterator it = iar.begin();//内置类型迭代器,it迭代器类型,begin获取顺序元素的第一个元素的位置信息 
	for (; it != iar.end(); ++it)//end代表顺序元素的最后一个元素的后续位置,78后面的后续位置 
	{
    
    
		cout << *it << endl;//迭代器从前向后依次访问 ,*it所指之物 
	}

	return 0;
}

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/LINZEYU666/article/details/112143516
Recomendado
Clasificación