C ++: Ensayo 7 --- sobrecarga del operador

Cuando realizamos la operación a + b, devuelve ab.

Ejemplo: darse cuenta de la suma de números complejos.

//用C++类的方法实现复数加法
#include<string>
#include<iostream>

class Plus//定义一个复数类
{
public:
	//构造函数有两种情况,一种是对这个类有初始化;另一种是没有初始化(没有初始化的话把他们都赋值为0)
	Plus();
	Plus(double r,double i);
	virtual ~Plus();//析构函数
	Plus add(Plus &d);//这个方法是实现复数加法的方案,函数返回值是一个类
	void printf();
private:
	double real;//实步
	double imag;//虚步
};
Plus::Plus()
{
	real = 0;
	imag = 0;
}
 Plus::Plus(double r, double i)//如果有初始化的话把两个参数赋值进两个变量里边
{
	 real = r;
	 imag = i;
}
 Plus::~Plus()
 {
 
 }
 Plus Plus::add(Plus &d)//参数就是被加数
 {
	 Plus c;//实例化一个复数类c
	 c.real = real + d.real;//把参数提取进来跟我自身的一个加数(自身的话因为是已经被主函数传进来的对象进行初始化了),使他们两个的实部相加
	 c.imag = imag + d.imag;
	 return c;
 }
 void Plus::printf()
 {
	 std::cout << "(" << real << "," <<imag<< "i)" << std::endl;
 }
int main()
{
	Plus p0(6, 5);
	Plus p1(3, 4);//实例化一个对象并初始化
	Plus p2(5, -8);
	Plus p3,p4;
	p3 = p1.add(p2);
	p4 = p0.add(p3);
	std::cout << "p1=";
	p1.printf();
	std::cout << "p2=";
	p2.printf();
	std::cout << "p1+p2=";
	p3.printf();
	std::cout << "p0+p1+p2=";
	p4.printf();


	return 0;
}

resultado:

Esto se logra mediante la definición de funciones relacionadas.

Sobrecarga del operador:

    

Vuelva a escribir la clase anterior para usar la sobrecarga del operador para lograr:

#include<string>
#include<iostream>
//对运算符+进行重载
class Complex//定义一个复数类
{
public:
	//构造函数有两种情况,一种是对这个类有初始化;另一种是没有初始化(没有初始化的话把他们都赋值为0)
	Complex();
	Complex(double r,double i);
	virtual ~Complex();//析构函数
	Complex operator+(Complex &d);//这个方法是实现复数加法的方案,函数返回值是一个类
	void printf();
private:
	double real;//实步
	double imag;//虚步
};
Complex::Complex()
{
	real = 0;
	imag = 0;
}
Complex::Complex(double r, double i)//如果有初始化的话把两个参数赋值进两个变量里边
{
	 real = r;
	 imag = i;
}
Complex::~Complex()
 {
 
 }
Complex Complex::operator+(Complex &d)//比如说a+b,那么他的参数就是b(那么a跑哪里去了为什么只有一个参数)(事实上就是a来调用operator+来加上参数d的)
 {
	Complex c;//实例化一个复数类c
	 c.real = real + d.real;//把参数提取进来跟我自身的一个加数(自身的话因为是已经被主函数传进来的对象进行初始化了),使他们两个的实部相加
	 c.imag = imag + d.imag;
	 return c;
 }
 void Complex::printf()
 {
	 std::cout << "(" << real << "," <<imag<< "i)" << std::endl;
 }
int main()
{
	Complex p0(6, 5);
	Complex p1(3, 4);//实例化一个对象并初始化
	Complex p2(5, -8);
	Complex p3,p4;
	p3 =p1+p2;//为什么可以直接加呢?因为加号在类里面已经被重载了(不用像原来一样调用函数实现加法了)
	std::cout << "p1=";
	p1.printf();
	std::cout << "p2=";
	p2.printf();
	std::cout << "p1+p2=";
	p3.printf();
	return 0;
}

El resultado es el mismo.

    
Función amiga (es decir, esta función no pertenece a esta clase, pero es amiga o pariente de esta clase, por lo que puede acceder a los miembros privados de esta clase) (¿Por qué quieres que las funciones de operador sean funciones amiga? Porque queremos acceder Si el miembro privado no es una función de esta clase, entonces no se puede acceder a su miembro privado. ¿Qué debo hacer? Solo a través de sus amigos)

Vuelva a escribir de la siguiente manera: pero este método no se recomienda, pero todos también deberían saberlo.

#include<string>
#include<iostream>
//对运算符+进行重载
class Complex//定义一个复数类
{
public:
	//构造函数有两种情况,一种是对这个类有初始化;另一种是没有初始化(没有初始化的话把他们都赋值为0)
	Complex();
	Complex(double r,double i);
	virtual ~Complex();//析构函数
	friend Complex operator+(Complex &c,Complex &d);//这个方法是实现复数加法的方案,函数返回值是一个类
	void printf();
private:
	double real;//实步
	double imag;//虚步
};
Complex::Complex()
{
	real = 0;
	imag = 0;
}
Complex::Complex(double r, double i)//如果有初始化的话把两个参数赋值进两个变量里边
{
	 real = r;
	 imag = i;
}
Complex::~Complex()
 {
 
 }
//注意这里作为友元函数不属于Complex,记得别写::
Complex operator+(Complex &c,Complex &d)
 {
	 return Complex(c.real+d.real,c.imag+d.imag);
 }
 void Complex::printf()
 {
	 std::cout << "(" << real << "," <<imag<< "i)" << std::endl;
 }
int main()
{
	Complex p0(6, 5);
	Complex p1(3, 4);//实例化一个对象并初始化
	Complex p2(5, -8);
	Complex p3,p4;
	p3 =p1+p2;
	std::cout << "p1=";
	p1.printf();
	std::cout << "p2=";
	p2.printf();
	std::cout << "p1+p2=";
	p3.printf();
	return 0;
}

El resultado final es el mismo.

25-32

-------- Gestión de memoria dinámica

Primero comprenda el concepto, ¿qué son la asignación de memoria estática y la asignación de memoria dinámica?

Asignación de memoria estática y asignación de memoria dinámica

La asignación estática de memoria: global o local variable (objeto), el compilador en tiempo de compilación se puede saber el tamaño del espacio de memoria necesario de acuerdo con el tipo de variable u objeto. Para que el sistema les asigne espacio de memoria cuando sea apropiado

Asignación de memoria dinámica: algunos objetos de operación solo se pueden determinar cuando el programa se está ejecutando, por lo que el compilador no puede reservar espacio de almacenamiento para ellos cuando se compila el programa . Solo cuando el programa se está ejecutando , el sistema asigna memoria de acuerdo con los requisitos de tiempo de ejecución , lo que se denomina asignación de memoria dinámica. . La asignación dinámica se realiza en el área de almacenamiento gratuito. (Esta gestión de la memoria es verdaderamente dinámica)

Utilice new para solicitar una dirección de tipo int (un bloque de memoria, 4 bytes en total) y asigne la primera dirección a esta variable de puntero, el nombre de la variable es i.

 

Por ejemplo, tenemos una dirección de 0 a 18, y una variable llamada i se declara en el espacio de la pila. I es una variable de puntero por lo que almacena una dirección. ¿De dónde proviene esta dirección? Un nuevo bloque de memoria int es generado por new, y su dirección inicial es devuelta para almacenarlo. La dirección inicial es 4, e int ocupa 4 bytes (4567 estos cuatro bytes son el bloque de memoria de new, y ponen su dirección inicial 4 Almacenado en esta variable de puntero)

La operación de eliminar i; es devolver los cuatro bloques de memoria de 4567 a nuestro sistema operativo, pero nuestra variable de puntero no ha cambiado, porque nuestra variable de puntero i es en realidad un local generado en la pila La variable, no se libera, su dirección sigue ahí, pero el contenido de esta dirección se libera, por lo que por seguridad, tenemos que poner i en NULL. De esta manera, se convierte en la siguiente imagen, y todo en i No más, ahora es un puntero obsoleto. Este puntero es inútil. Si intentamos desreferenciar el puntero asignado a NULL, entonces saldrá mal.

 

 

#include<stdio.h>
#include<iostream>
#include<string>
class Company
{
 public:
	 Company(std::string theName);
	 virtual void printInfo();
 protected:
	std::string name;
};
class TechCompany :public Company
{
public:
	TechCompany(std::string theName, std::string product);
	virtual void printInfo();
private:
	std::string product;
};
Company::Company(std::string theName)
{
	name = theName;
}
void Company::printInfo()
{
	std::cout << "这个公司的名字叫:" << name << std::endl;
}
TechCompany::TechCompany(std::string theName, std::string product):Company(theName)
{
	this->product = product;

}
void TechCompany::printInfo()
{
	std::cout << name << "公司主打产品是:" << product << std::endl;
}
int main()
{
	Company *company = new Company("apple");
	company->printInfo();
	delete company;
	company = NULL;
	company = new TechCompany("apple", "苹果");
	company->printInfo();
	delete company;
	company = NULL;
	return 0;
}

Matriz dinámica:

 

 

Eliminar una matriz dinámica:

#include<iostream>
#include<string>
int main()
{
	unsigned int count = 0;//count是用来动态的定义的
	std::cout << "请输入数据元素的个数:" << std::endl;
	std::cin >> count;//输入存放到count里面
	int *x = new int[count];//定义一个指针,用new来对它进行初始化,给他申请内存,这块的申请内存是在程序运行的时候申请的,而不是编译的时候申请的,所以我们说他是动态内存,
	//是从堆里边申请的,而不是栈里边,一般我们像变量,局部变量是从栈里边申请的数据,而这些动态申请呢我们程序由程序在运行的时候申请的,这些是从堆里边申请的,只是两块不同的内存。
	for (int i = 0; i < count; i++)//初始化
	{
		x[i] = i;
	}
	for (int i = 0; i < count; i++)//打印
	{
		std::cout << "x[" << i << "]=" << x[i] << std::endl;
	}
	return 0;
}

  Debido a que estamos asignados usando la nueva declaración, su memoria se asigna en el montón y no se liberará con el final de nuestra función. Si es una variable local, el programa la asigna automáticamente en la pila (la asigna automáticamente el compilador) y se liberará automáticamente al final de la llamada a la función.

//从函数和方法返回内存
#include<iostream>
int *newInt(int value);//1声明一个函数,这个函数前边加一个*号,说明他的返回值类型是int*,是一个指向整型变量的一个地址,一个指针
int main()
{
	int *x = newInt(20);//2、6定义一个指针变量x,这是一个指向整数的指针变量,他赋值为newInt(20)这个函数的返回值,因为这个函数的返回值是一个地址,
	//因为声明函数的时候加了一个*号是一个指针的标志,说明他的返回值是一个地址。调用他
	std::cout << *x<<std::endl;//7打印地址
	delete x;//8把他释放掉
	x = NULL;//9把他的指针填充NULL,使得指针不会被随意的乱用
	return 0;//然后结束整个程序
}
int *newInt(int value)
{
	int *myInt = new int;//3这个里边它new一个整型的变量,在堆里边申请一个整型的内存块
	*myInt = value;//4然后给他赋值,赋值为这个参数value的值(*myInt使用*给他解引用)
	return myInt;//5赋值之后返回他的地址(6处接到地址)
}

 // ¿Por qué no dejar que la función devuelva un puntero a una variable local?

Llamar por dirección:

#include<iostream>
void swap(int *x, int *y);
int main()
{
	int a, b;
	a = 3;
	b = 5;
	swap(&a, &b);//传引用过去,传他们的地址过去
	std::cout << "a=" << a << std::endl;
	std::cout << "b=" << b << std::endl;
	return 0;
}
void swap(int *x, int *y)//这里要接的两个形参定义为指针类型,我们就可以接到他的地址
{
#if 0
	int temp;
	temp = *x;
	*x = *y;
	*y = temp;
#endif
	*x ^= *y;
	*y ^= *x;
	*x ^= *y;
}

Ninguna función debería tomar el puntero de su propia variable local como valor de retorno, porque la variable local está en la pila y se liberará automáticamente al final de la función. (Debido a que la pila se liberará al final de esta función, por lo que devuelve su dirección. La dirección a la que hicimos referencia en el código principal de la función principal será un valor impredecible. Debido a que se libera, solo hay un valor basura dentro. O otras variables pueden estar equivocadas)

Si desea que una función devuelva un puntero sin dejar ningún peligro oculto, solo puede ser la dirección base de un bloque de memoria asignado dinámicamente. (Debido a la asignación dinámica, solo la declaración de eliminación puede liberarlo en el montón).

PD: enfatiza dos conceptos

Puntero de función : (énfasis en el puntero de dos palabras) muestra que este puntero de función es en realidad un puntero, es una variable de dirección de almacenamiento. (Variable puntero apuntando a la primera dirección de la función)

#include<stdio.h>
int fun(int x, int y);
int main()
{
	int i, a, b;
	int(*p)(int a,int b);//声明函数指针,前边多了括号(*p)(说明他是一个指针变量,指向函数的指针变量)后边的(),表明它是一个函数
	scanf("%d", &a);
	p = fun;//给函数指针p赋值,使他指向函数f
	printf("请输入个数字:\n");
	for (i = 0; i < 10; i++)
	{
		scanf("%d", &b);
		a = (*p)(a, b);//通过指针p调用函数f。(p来代替fun)
	}
	printf("The max number is:%d", a);
	return 0;
}
int fun(int x, int y)
{
	int z; 
	z = (x > y) ? x : y;
	return(z);
}

Función de puntero :

Una función puede traer de vuelta un valor de datos entero, un valor de tipo de carácter y un valor de tipo real. También puede traer de vuelta datos de tipo puntero para apuntar a una unidad de dirección.

#include<iostream>
int *newInt(int value);//1声明一个函数(前边*newInt没有用括号括起来,说明是一个函数,括起来的话就是一个指针了),这个函数前边加一个*号,说明他的返回值类型是int*,是一个指向整型变量的一个地址,一个指针
int main()
{
	int *x = newInt(20);//2、6定义一个指针变量x,这是一个指向整数的指针变量,他赋值为newInt(20)这个函数的返回值,因为这个函数的返回值是一个地址,
	//因为声明函数的时候加了一个*号是一个指针的标志,说明他的返回值是一个地址。调用他
	std::cout << *x<<std::endl;//7打印地址
	delete x;//8把他释放掉
	x = NULL;//9把他的指针填充NULL,使得指针不会被随意的乱用
	return 0;//然后结束整个程序
}
int *newInt(int value)
{
	int *myInt = new int;//3这个里边它new一个整型的变量,在堆里边申请一个整型的内存块
	*myInt = value;//4然后给他赋值,赋值为这个参数value的值(*myInt使用*给他解引用)
	return myInt;//5赋值之后返回他的地址(6处接到地址)
}

----- Copiar constructor

 

36-38

Supongo que te gusta

Origin blog.csdn.net/m0_37957160/article/details/109014853
Recomendado
Clasificación