minhas informações de contato
Correspondência[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Em C/C++, há um grande número de variáveis, funções e classes a serem aprendidas posteriormente. Os nomes dessas variáveis, funções e classes existirão em todo o mundo.
No âmbito local, pode causar muitos conflitos.O objetivo do uso de namespaces é localizar os nomes dos identificadores para evitar nomenclatura
Conflito ou poluição de nomes, a palavra-chave namepac parece resolver esse problema.
Conflitos de nomenclatura como o programa a seguir em projetos de linguagem C são problemas comuns que o C++ introduz o namepac para melhor resolvê-los.
Tal problema: (O erro é relatado porque a variável rand que definimos entra em conflito com a função rand em stdlib.h)
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”
printf("%dn", rand);
return 0;
}
1. Para definir um namespace, você precisa usar a palavra-chave namespace, seguida pelo nome do namespace e, em seguida, conectar um par de {}, onde {}
Ou seja, um membro do namespace. Variáveis/funções/tipos, etc. podem ser definidos no namespace.(Observe que {} não é seguido por ";")。
2. A essência do namespace é definir um domínio. Este domínio é independente do domínio global. Diferentes domínios podem definir variáveis com o mesmo nome.
O rand acima não está mais em conflito.
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
namespace tmp
{
int rand = 0;
}
int main()
{
printf("%dn", rand);
return 0;
}
3. Os domínios em C++ incluem domínio local de função, domínio global, domínio de namespace e domínio de classe. O domínio afeta a sintaxe de tempo de compilação para encontrar uma variável/função/;
A lógica do tipo origem (declaração ou definição), com isolamento de domínio, os conflitos de nomes são resolvidos.Além de afetar o domínio local e o domínio global
A compilação da lógica de pesquisa também afetará o ciclo de declaração de variáveis. Os domínios de namespace e os domínios de classe não afetam o ciclo de declaração de variáveis.
4. O namespace só pode ser definido globalmente e, claro, também pode ser aninhado.
#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. Namespaces com o mesmo nome definidos em vários arquivos do projeto serão considerados como um namespace e não entrarão em conflito.
arquivo teste.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;
}
arquivo teste.h
#pragma once
namespace tmp
{
int d = 0;
}
Pode-se descobrir que a variável d no espaço tmp pode ser usada no arquivo .c.
6. A biblioteca padrão C++ é colocada em um namespace chamado std (padrão).
7. Se quisermos usar variáveis no domínio global, podemos fazer isto:
int a = 3;
int main()
{
int a = 0;
printf("%dn", ::a);
return 0;
}
Desta forma, printf imprime 3 primeiro.
Ao compilar para buscar a declaração/definição de uma variável, por padrão ela buscará apenas local ou globalmente, não no namespace.então
O programa a seguir irá compilar e relatar um erro.
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;
}
Portanto, temos que usar variáveis/funções definidas no namespace. Existem três maneiras:
1. Especifique o acesso ao namespace. Este método é recomendado no projeto.
tmp::d
2. Usar expande um membro do namespace.Essa abordagem é recomendada para membros do projeto acessados com frequência e que não têm conflitos.
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. Expanda todos os membros no namespace,O projeto não é recomendado porque o risco de conflito é alto. O programa de prática diária é recomendado por conveniência.
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. É a abreviatura de Input Output Stream. É uma biblioteca de fluxo de entrada e saída padrão que define entrada e saída padrão.
fora do objeto.
2. std::cin é um objeto da classe istream, que é orientado principalmente para a saída padrão de caracteres estreitos (do tipo char).
Ingresso.
3. std::cout é um objeto da classe ostream, que é orientado principalmente para o fluxo de saída padrão de caracteres estreitos.
4. std::endl é uma função Quando o fluxo é inserido na saída, é equivalente a inserir um caractere de nova linha e atualizar o buffer.
5. << é o operador de inserção de fluxo e >> é o operador de extração de fluxo. (A linguagem C também usa esses dois operadores para realizar operações bit a bit, como deslocamento para a esquerda/deslocamento para a direita)
6. É mais conveniente usar C++ para entrada e saída. Não há necessidade de especificar manualmente o formato como printf/scanf para entrada e saída C**++.
A saída pode identificar automaticamente tipos de variáveis(Essencialmente, isso é conseguido através da sobrecarga de funções). Na verdade, o mais importante é que os fluxos C++ possam suportar melhor a personalização.
Digite objetos de entrada e saída.
#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, etc. todos pertencem à biblioteca padrão C++. A biblioteca padrão C++ é colocada em um namespace chamado std (padrão), portanto, é necessário.
Use-os por meio do uso de namespace.
8、⼼Podemos usar namespace std na prática diária geral, mas não é recomendado usar namespace std no desenvolvimento real do projeto.
Os parâmetros padrão especificam um valor padrão para os parâmetros da função ao declarar ou definir a função.Ao chamar esta função, se nenhum parâmetro real for especificado
Em seguida, o valor padrão do parâmetro formal é usado, caso contrário, o parâmetro real especificado é usado. Os parâmetros padrão são divididos em parâmetros padrão completos e semi-padrão. (Em alguns lugares,
Os parâmetros padrão também são chamados de parâmetros padrão).
Padrão completo significa que todos os parâmetros formais recebem valores padrão, e semi-padrão significa que alguns parâmetros formais recebem valores padrão.C++ estipula que os parâmetros semi-padrão devem ser da direita para a esquerda
Contínuo é padronizado em sequência e não pode pular para o valor padrão em intervalos.
Para chamadas de função com parâmetros padrão, o C++ estipula que os parâmetros reais devem ser fornecidos sequencialmente da esquerda para a direita e os parâmetros reais não podem ser ignorados.
Quando a declaração e a definição da função são separadas, os parâmetros padrão não podem aparecer tanto na declaração quanto na definição da função. É estipulado que a função deve ser declarada como padrão.
valor.
#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;
}
O semi-padrão não pode ser escrito assim:
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 cumprir rigorosamente:
Os parâmetros semi-padrão devem ser padronizados continuamente da direita para a esquerda e não podem ser ignorados para os valores padrão em intervalos.
Antes de aprendermos C++, quando implementamos a inicialização e inserção de pilha, escrevemos isto:
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 quisermos inserir 100 dados, precisaremos de expansão contínua e perda eficiente, mas depois de aprendermos os parâmetros padrão, podemos escrever assim:
// 栈顶
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;
}
Isso evita efetivamente o problema de abrir espaço repetidamente.
C++ suporta funções com o mesmo nome que aparecem no mesmo escopo, mas exige que os parâmetros formais dessas funções com o mesmo nome sejam diferentes.
Tipos diferentes. Dessa forma, as chamadas de função C++ exibem comportamento polimórfico e são mais flexíveis de usar. (No entanto, valores de retorno diferentes não podem ser usados como condições de sobrecarga.
Como não pode ser distinguido durante a chamada, se o valor de retorno e o tipo ou número do parâmetro mudarem ao mesmo tempo, também é uma condição de sobrecarga).
#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;
}
Em particular, se o método acima usar parâmetros padrão, um erro será relatado ao chamar sem passar parâmetros. O compilador não sabe quem chamar.
// 下⾯两个函数构成重载
// 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;
}``
resultado: