Berbagi teknologi

Pengenalan pertama ke c (namespace, parameter default, kelebihan fungsi)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. Ruang nama

1. Arti dari namespace

Di C/C++, ada banyak sekali variabel, fungsi dan kelas yang harus dipelajari nanti. Nama-nama variabel, fungsi dan kelas ini akan ada di seluruh dunia.

Dalam lingkup lokal, hal ini dapat menimbulkan banyak konflik.Tujuan penggunaan namespace adalah untuk melokalisasi nama pengidentifikasi untuk menghindari penamaan

Konflik atau polusi nama, kata kunci namepac muncul untuk mengatasi masalah ini.

Konflik penamaan seperti program berikut dalam proyek bahasa C adalah masalah umum. C++ memperkenalkan namepac untuk menyelesaikannya dengan lebih baik.

Masalah seperti ini: (Kesalahan dilaporkan karena variabel rand yang kita atur bertentangan dengan fungsi rand di stdlib.h)

#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
	// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”
	printf("%dn", rand);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2. Definisi namespace

1. Untuk mendefinisikan namespace, Anda perlu menggunakan kata kunci namespace, diikuti dengan nama namespace, lalu menghubungkan sepasang {}, di mana {}

Artinya, anggota namespace. Variabel/fungsi/tipe, dll. dapat didefinisikan di namespace.(Perhatikan bahwa {} tidak diikuti oleh ";")

2. Inti dari namespace adalah untuk mendefinisikan sebuah domain. Domain ini tidak bergantung pada domain global.Domain yang berbeda dapat mendefinisikan variabel dengan nama yang sama, sebagai berikut

Rand di atas tidak lagi berkonflik.

#include<iostream>
#include <stdio.h>
#include <stdlib.h>
namespace tmp
{
	int rand = 0;
}
int main()
{
	printf("%dn", rand);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3. Domain di C++ meliputi domain fungsi lokal, domain global, domain namespace, dan domain kelas; domain mempengaruhi sintaks waktu kompilasi untuk menemukan variabel/fungsi/;

Logika asal tipe (deklarasi atau definisi), dengan isolasi domain, konflik nama diselesaikan.Selain mempengaruhi domain lokal dan domain global

Mengkompilasi logika pencarian juga akan mempengaruhi siklus deklarasi variabel. Domain namespace dan domain kelas tidak mempengaruhi siklus deklarasi variabel.

4. Namespace hanya dapat didefinisikan secara global, dan tentunya juga dapat disarangkan.

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

5. Namespace dengan nama yang sama yang ditentukan dalam beberapa file dalam proyek akan dianggap sebagai satu namespace dan tidak akan konflik.

file tes.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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

file tes.h

#pragma once
namespace tmp
{
	int d = 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5

Terlihat bahwa variabel d di ruang tmp dapat digunakan di file .c.

6. Pustaka standar C++ ditempatkan di namespace yang disebut std (standar).

7. Jika kita ingin menggunakan variabel di domain global, kita bisa melakukan ini:

int a = 3;
int main()
{
	int a = 0;
	printf("%dn", ::a);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Dengan cara ini, printf mencetak 3 terlebih dahulu.

3. Penggunaan namespace

Saat kompilasi untuk mencari deklarasi/definisi suatu variabel, secara default hanya akan mencari secara lokal atau global, bukan di namespace.Jadi

Program berikut akan mengkompilasi dan melaporkan kesalahan.

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Jadi kita harus menggunakan variabel/fungsi yang didefinisikan dalam namespace. Ada tiga cara:

1. Tentukan akses namespace. Metode ini direkomendasikan dalam proyek.

tmp::d
  • 1

2. Menggunakan memperluas anggota namespace.Pendekatan ini direkomendasikan untuk anggota proyek yang sering diakses dan tidak mengalami konflik.

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3. Perluas semua anggota di namespace,Proyek ini tidak direkomendasikan karena risiko konfliknya tinggi. Program latihan harian direkomendasikan untuk kenyamanan.

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

2. Masukan dan keluaran

1. Ini adalah singkatan dari Input Output Stream. Ini adalah pustaka aliran input dan output standar yang mendefinisikan input dan output standar.

keluar objek.

2. std::cin adalah objek kelas istream, yang terutama berorientasi pada keluaran standar karakter sempit (tipe char).

Arus masuk.

3. std::cout adalah objek kelas ostream, yang terutama berorientasi pada aliran keluaran standar karakter sempit.

4. std::endl adalah sebuah fungsi. Ketika aliran dimasukkan ke dalam output, itu setara dengan memasukkan karakter baris baru dan menyegarkan buffer.

5. &lt;&lt; adalah operator penyisipan aliran, dan &gt;&gt; adalah operator ekstraksi aliran. (Bahasa C juga menggunakan kedua operator ini untuk melakukan operasi bitwise seperti shift kiri/shift kanan)

6. Lebih mudah menggunakan C++ untuk input dan output. Tidak perlu menentukan format secara manual seperti printf/scanf untuk input dan output C**++.

Output dapat secara otomatis mengidentifikasi tipe variabel(Pada dasarnya, ini dicapai melalui kelebihan fungsi). Faktanya, hal yang paling penting adalah aliran C++ dapat mendukung penyesuaian dengan lebih baik.

Ketik objek input dan 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

7. cout/cin/endl, dll. semuanya milik pustaka standar C++. Pustaka standar C++ ditempatkan di namespace yang disebut std (standar), jadi perlu

Gunakan mereka melalui penggunaan namespace.

8、⼼Kita dapat menggunakan namespace std dalam praktik umum sehari-hari, tetapi tidak disarankan untuk menggunakan namespace std dalam pengembangan proyek sebenarnya.

3. Parameter bawaan

1. Definisi dan peraturan parameter default

Parameter default menentukan nilai default untuk parameter fungsi saat mendeklarasikan atau mendefinisikan fungsi.Saat memanggil fungsi ini, jika tidak ada parameter sebenarnya yang ditentukan

Kemudian nilai default dari parameter formal digunakan, jika tidak, parameter aktual yang ditentukan digunakan. Parameter default dibagi menjadi parameter default penuh dan semi-default. (Di beberapa tempat,

Parameter default disebut juga parameter default).

Default penuh berarti semua parameter formal diberi nilai default, dan semi-default berarti beberapa parameter formal diberi nilai default.C++ menetapkan bahwa parameter semi-default harus dari kanan ke kiri

Default berkelanjutan secara berurutan, dan tidak dapat melompat ke nilai default secara berkala.

Untuk pemanggilan fungsi dengan parameter default, C++ menetapkan bahwa parameter aktual harus diberikan secara berurutan dari kiri ke kanan, dan parameter aktual tidak dapat dilewati.

Ketika deklarasi dan definisi fungsi dipisahkan, parameter default tidak dapat muncul dalam deklarasi dan definisi fungsi. Ditetapkan bahwa fungsi tersebut harus dideklarasikan sebagai default

nilai.

#include <iostream>
using namespace std;
void Func(int a = 0)
{
	cout << a << endl;
}
int main()
{
	Func(); // 没有传参时,使⽤参数的默认值
	Func(10); // 传参时,使⽤指定的实参
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Masukkan deskripsi gambar di sini

2. Default penuh dan semi-default

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

Semi-default tidak dapat ditulis seperti ini:

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Harus benar-benar mematuhi:

Parameter semi-default harus terus-menerus ditetapkan secara default dari kanan ke kiri, dan tidak dapat dilewati ke nilai default secara berkala.

3. Penerapan praktis parameter default

Sebelum kita mempelajari C++, ketika kita mengimplementasikan inisialisasi dan penyisipan tumpukan, kita menulis ini:

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++;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

Jika kita ingin memasukkan 100 buah data, kita memerlukan perluasan terus menerus dan kehilangan yang efisien, tetapi setelah kita mempelajari parameter default, kita dapat menulis seperti ini:

// 栈顶
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

Ini secara efektif menghindari masalah pembukaan ruang berulang kali.

4. Fungsi kelebihan beban

C++ mendukung fungsi dengan nama yang sama yang muncul dalam cakupan yang sama, tetapi mengharuskan parameter formal dari fungsi dengan nama yang sama berbeda

Jenis yang berbeda. Dengan cara ini, pemanggilan fungsi C++ menunjukkan perilaku polimorfik dan lebih fleksibel untuk digunakan. (Namun, nilai pengembalian yang berbeda tidak dapat digunakan sebagai kondisi kelebihan beban.

Karena tidak bisa dibedakan saat pemanggilan, jika nilai kembalian dan jenis atau nomor parameter berubah secara bersamaan, itu juga merupakan kondisi kelebihan beban).

1. Jenis parameter yang berbeda

#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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2. Jumlah parameter berbeda

// 2、参数个数不同
void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Khususnya, jika metode di atas menggunakan parameter default, kesalahan akan dilaporkan saat memanggil tanpa meneruskan parameter.

// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void f1()
{
	cout << "f()" << endl;
}
void f1(int a = 10)
{
	cout << "f(int a)" << endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3. Urutan parameternya berbeda-beda (sebenarnya jenis parameternya berbeda-beda)

// 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
#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;
}``

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

hasil:
Masukkan deskripsi gambar di sini