le mie informazioni di contatto
Posta[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
In C/C++ ci sono un gran numero di variabili, funzioni e classi da apprendere in seguito. I nomi di queste variabili, funzioni e classi esisteranno in tutto il mondo.
Nell'ambito locale, può causare molti conflitti.Lo scopo dell'utilizzo degli spazi dei nomi è localizzare i nomi degli identificatori per evitare la denominazione
Conflitto o inquinamento dei nomi, la parola chiave namepac sembra risolvere questo problema.
I conflitti di denominazione come il seguente programma nei progetti in linguaggio C sono problemi comuni. C++ introduce namepac per risolverli meglio.
Un problema del genere: (L'errore viene segnalato perché la variabile rand che abbiamo impostato è in conflitto con la funzione rand in stdlib.h)
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”
printf("%dn", rand);
return 0;
}
1. Per definire uno spazio dei nomi, è necessario utilizzare la parola chiave namespace, seguita dal nome dello spazio dei nomi, quindi collegare una coppia di {}, dove {}
Cioè, un membro dello spazio dei nomi. Variabili/funzioni/tipi, ecc. possono essere definiti nello spazio dei nomi.(Nota che {} non è seguito da ";")。
2. L'essenza del namespace è definire un dominio. Questo dominio è indipendente dal dominio globale. Diversi domini possono definire variabili con lo stesso nome, quindi quanto segue
Il rand sopra non è più in conflitto.
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
namespace tmp
{
int rand = 0;
}
int main()
{
printf("%dn", rand);
return 0;
}
3. I domini in C++ includono il dominio locale della funzione, il dominio globale, il dominio dello spazio dei nomi e il dominio della classe. Il dominio influenza la sintassi in fase di compilazione per trovare una variabile/funzione/;
La logica del tipo origine (dichiarazione o definizione), con l'isolamento del dominio, i conflitti di nome vengono risolti.Oltre a influenzare il dominio locale e il dominio globale
La compilazione della logica di ricerca influenzerà anche il ciclo di dichiarazione delle variabili. I domini dello spazio dei nomi e i domini delle classi non influiscono sul ciclo di dichiarazione delle variabili.
4. Lo spazio dei nomi può essere definito solo globalmente e ovviamente può anche essere annidato.
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
namespace tmp
{
int rand = 0;
namespace tmp1
{
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
}
int main()
{
printf("%dn", rand);
return 0;
}
5. Gli spazi dei nomi con lo stesso nome definito in più file nel progetto saranno considerati come un unico spazio dei nomi e non saranno in conflitto.
file test.c
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include"test.h"
namespace tmp
{
int rand = 0;
namespace tmp1
{
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
}
int main()
{
printf("%dn", tmp::d);
return 0;
}
file prova.h
#pragma once
namespace tmp
{
int d = 0;
}
Si può scoprire che la variabile d nello spazio tmp può essere utilizzata nel file .c.
6. La libreria standard C++ viene inserita in uno spazio dei nomi chiamato std (standard).
7. Se vogliamo utilizzare variabili nel dominio globale, possiamo farlo:
int a = 3;
int main()
{
int a = 0;
printf("%dn", ::a);
return 0;
}
In questo modo printf stampa prima 3.
Durante la compilazione per cercare la dichiarazione/definizione di una variabile, per impostazione predefinita la ricerca verrà eseguita solo localmente o globalmente, non nello spazio dei nomi.COSÌ
Il seguente programma compilerà e segnalerà un errore.
namespace tmp
{
int d = 0;
namespace tmp1
{
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
}
int main()
{
int a = 0;
printf("%dn", d);//未定义标识符d
return 0;
}
Quindi dobbiamo utilizzare variabili/funzioni definite nello spazio dei nomi. Esistono tre modi:
1. Specificare l'accesso allo spazio dei nomi Questo metodo è consigliato nel progetto.
tmp::d
2. Utilizzando espande un membro dello spazio dei nomi.Questo approccio è consigliato per i membri del progetto a cui si accede frequentemente che non presentano conflitti.
namespace tmp
{
int d = 0;
namespace tmp1
{
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
}
using tmp::d;
int main()
{
int a = 0;
printf("%dn", d);//未定义标识符d
return 0;
}
3. Espandi tutti i membri nello spazio dei nomi,Il progetto non è consigliato perché il rischio di conflitto è elevato. Il programma di pratica quotidiana è consigliato per comodità.
namespace tmp
{
int d = 0;
namespace tmp1
{
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
}
using namespace tmp;
int main()
{
int a = 0;
printf("%dn", d);//未定义标识符d
return 0;
}
1. È l'abbreviazione di Input Output Stream È una libreria di flussi di input e output standard che definisce input e output standard.
fuori oggetto.
2. std::cin è un oggetto della classe istream, che è principalmente orientato all'output standard di caratteri stretti (di tipo char).
Afflusso.
3. std::cout è un oggetto della classe ostream, che è principalmente orientato al flusso di output standard di caratteri stretti.
4. std::endl è una funzione. Quando lo stream viene inserito nell'output, equivale a inserire un carattere di nuova riga e aggiornare il buffer.
5. << è l'operatore di inserimento del flusso e >> è l'operatore di estrazione del flusso. (Il linguaggio C utilizza questi due operatori anche per eseguire operazioni bit a bit come lo spostamento a sinistra/lo spostamento a destra)
6. È più conveniente utilizzare C++ per input e output Non è necessario specificare manualmente il formato come printf/scanf input e output C**++ input**.
L'output può identificare automaticamente i tipi di variabile(Essenzialmente, ciò si ottiene tramite l'overload delle funzioni). In effetti, la cosa più importante è che i flussi C++ possano supportare meglio la personalizzazione.
Digitare oggetti di input e output.
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
namespace tmp
{
int a = 0;
double b = 0.0;
char c = '0';
namespace tmp1
{
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
}
using namespace tmp;
using namespace std;
int main()
{
cin >> a >> b >> c;
cout << a << b << c;
return 0;
}
7. cout/cin/endl, ecc. appartengono tutti alla libreria standard C++ La libreria standard C++ è posizionata in uno spazio dei nomi chiamato std (standard), quindi è necessario
Usali attraverso l'utilizzo dello spazio dei nomi.
8、⼼Possiamo utilizzare namespace std negli esercizi quotidiani generali, ma non è consigliabile utilizzare namespace std nello sviluppo vero e proprio del progetto.
I parametri predefiniti specificano un valore predefinito per i parametri della funzione quando si dichiara o si definisce la funzione.Quando si chiama questa funzione, se non vengono specificati parametri effettivi
Quindi viene utilizzato il valore predefinito del parametro formale, altrimenti viene utilizzato il parametro effettivo specificato. I parametri predefiniti sono suddivisi in parametri completamente predefiniti e semi-predefiniti. (In alcuni posti,
I parametri predefiniti sono anche chiamati parametri predefiniti).
Predefinito completo significa che a tutti i parametri formali vengono assegnati valori predefiniti, mentre semi-predefinito significa che ad alcuni parametri formali vengono assegnati valori predefiniti.C++ stabilisce che i parametri semipredefiniti devono essere da destra a sinistra
Impostazioni predefinite continue in sequenza e impossibile passare al valore predefinito a intervalli.
Per le chiamate di funzione con parametri predefiniti, C++ stabilisce che i parametri effettivi devono essere forniti in sequenza da sinistra a destra e che i parametri effettivi non possono essere saltati.
Quando la dichiarazione e la definizione della funzione sono separate, i parametri predefiniti non possono apparire sia nella dichiarazione che nella definizione della funzione. Si stabilisce che la funzione deve essere dichiarata come predefinita
valore.
#include <iostream>
using namespace std;
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func(); // 没有传参时,使⽤参数的默认值
Func(10); // 传参时,使⽤指定的实参
return 0;
}
#include <iostream>
using namespace std;
// 全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
int main()
{
Func1();
Func1(1);
Func1(1, 2);
Func1(1, 2, 3);
Func2(100);
Func2(100, 200);
Func2(100, 200, 300);
return 0;
}
Il semi-default non può essere scritto in questo modo:
void Func2(int a = 10, int b, int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
//或者
void Func2(int a = 10, int b, int c)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
Deve attenersi rigorosamente a:
I parametri semi-predefiniti devono essere impostati continuamente da destra a sinistra e non possono essere saltati ai valori predefiniti a intervalli.
Prima di imparare il C++, quando abbiamo implementato l'inizializzazione e l'inserimento dello stack, abbiamo scritto quanto segue:
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
// 栈顶
void STInit(ST* ps, int n)
{
assert(ps);
ps->a = (STDataType*)malloc(n * sizeof(STDataType));
ps->top = 0;
ps->capacity = n;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
// 满了, 扩容
if (ps->top == ps->capacity)
{
printf("扩容n");
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity
* 2;
STDataType* tmp = (STDataType*)realloc(ps->a,
newcapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
Se vogliamo inserire 100 dati avremo bisogno di espansione continua e perdita efficiente, ma dopo aver appreso i parametri di default possiamo scrivere così:
// 栈顶
void STInit(ST* ps, int n = 4)
{
assert(ps);
ps->a = (STDataType*)malloc(n * sizeof(STDataType));
ps->top = 0;
ps->capacity = n;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
// 满了, 扩容
if (ps->top == ps->capacity)
{
printf("扩容n");
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity
* 2;
STDataType* tmp = (STDataType*)realloc(ps->a,
newcapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
int main()
{
ST a;
STInit(&a, 100);//这里不传100也可以,因为规定必须从左到右依次给实参,不能跳跃给实参。刚好和缺省参数确定位置互补
for (int i = 0; i < 100; i++)
{
STPush(&a, i);
}
return 0;
}
Ciò evita efficacemente il problema di aprire ripetutamente lo spazio.
C++ supporta funzioni con lo stesso nome che appaiono nello stesso ambito, ma richiede che i parametri formali di queste funzioni con lo stesso nome siano diversi. Può trattarsi di un numero diverso di parametri o
Tipi diversi. In questo modo, le chiamate di funzione C++ mostrano un comportamento polimorfico e sono più flessibili da utilizzare. (Tuttavia, valori restituiti diversi non possono essere utilizzati come condizioni di sovraccarico.
Poiché non è possibile distinguerlo durante la chiamata, se il valore restituito e il tipo o il numero del parametro cambiano contemporaneamente, si tratta anche di una condizione di sovraccarico).
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
In particolare, se il metodo precedente utilizza parametri predefiniti, verrà segnalato un errore quando si chiama senza passare parametri. Il compilatore non sa chi chiamare.
// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void f1()
{
cout << "f()" << endl;
}
void f1(int a = 10)
{
cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
int main()
{
Add(10, 20);
Add(10.1, 20.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}
`#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
int main()
{
Add(10, 20);
Add(10.1, 20.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}``
risultato: