BeginnersBook-C---教程-一-
BeginnersBook C++ 教程(一)
C++ 中的for
循环
循环用于重复执行语句块,直到满足特定条件。例如,当您显示从 1 到 100 的数字时,您可能希望将变量的值设置为 1 并将其显示 100 次,在每次循环迭代时将其值增加 1。
在 C++ 中,我们有三种类型的基本循环:for
,while
和do-while
。在本教程中,我们将学习如何在 C++ 中使用for
循环。
for
循环的语法
for(initialization; condition ; increment/decrement)
{
C++ statement(s);
}
for
循环的执行流程
当程序执行时,解释器总是跟踪将要执行的语句。我们将其称为控制流程或程序的执行流程。
第一步:在for
循环中,初始化只发生一次,这意味着for
循环的初始化部分只执行一次。
第二步: for
循环中的条件在每次循环迭代时进行计算,如果条件为真,则for
循环体内的语句将被执行。一旦条件返回false
,for
循环中的语句就不会执行,并且控制被转移到程序中for
循环后的下一个语句。
第三步:每次执行for
循环体后,for
循环的递增/递减部分更新循环计数器。
第四步:第三步后,控制跳转到第二步,重新求值条件。
从第二到第四的步骤重复,直到循环条件返回
false
。
C++ 中的简单for
循环示例
这里,在循环初始化部分中,将变量i
的值设置为 1,条件是i <= 6
,并且在每次循环迭代中,i
的值递增 1。
#include <iostream>
using namespace std;
int main(){
for(int i=1; i<=6; i++){
/* This statement would be executed
* repeatedly until the condition
* i<=6 returns false.
*/
cout<<"Value of variable i is: "<<i<<endl;
}
return 0;
}
输出:
Value of variable i is: 1
Value of variable i is: 2
Value of variable i is: 3
Value of variable i is: 4
Value of variable i is: 5
Value of variable i is: 6
C++ 中的无限循环
当循环重复执行并且永不停止时,循环被认为是无限的。这通常是错误的。当你在for
循环中设置条件时它永远不会返回false
,它就会变成无限循环。
例如:
#include <iostream>
using namespace std;
int main(){
for(int i=1; i>=1; i++){
cout<<"Value of variable i is: "<<i<<endl;
}
return 0;
}
这是一个无限循环,因为我们递增i
的值,因此它总是满足条件i <= 1
,条件永远不会返回false
。
这是无限for
循环的另一个例子:
// infinite loop
for ( ; ; ) {
// statement(s)
}
示例:使用for
循环显示数组元素
#include <iostream>
using namespace std;
int main(){
int arr[]={21,9,56,99, 202};
/* We have set the value of variable i
* to 0 as the array index starts with 0
* which means the first element of array
* starts with zero index.
*/
for(int i=0; i<5; i++){
cout<<arr[i]<<endl;
}
return 0;
}
输出:
21
9
56
99
202
C++ 中的while
循环
在上一篇教程中,我们讨论了for
循环 。在本教程中,我们将讨论while
循环。如前所述,循环用于重复执行程序语句块,直到给定的循环条件返回false
。
while
循环的语法
while(condition)
{
statement(s);
}
循环如何工作?
在while
循环中,首先计算条件,如果它返回true
,则执行while
循环中的语句,这会重复发生,直到条件返回false
。当条件返回false
时,控制流退出循环并跳转到程序中的while
循环后的下一个语句。
注意:使用while
循环时要注意的重点是,我们需要在while
循环中使用递增或递减语句,以便循环变量在每次迭代时都会发生变化,并且在某些情况下返回false
。这样我们就可以结束while
循环的执行,否则循环将无限期地执行。
while
循环流程图
C++中的while
循环示例
#include <iostream>
using namespace std;
int main(){
int i=1;
/* The loop would continue to print
* the value of i until the given condition
* i<=6 returns false.
*/
while(i<=6){
cout<<"Value of variable i is: "<<i<<endl; i++;
}
}
输出:
Value of variable i is: 1
Value of variable i is: 2
Value of variable i is: 3
Value of variable i is: 4
Value of variable i is: 5
Value of variable i is: 6
无限循环
永远不停止的while
循环被认为是无限循环,当我们以这样的方式给出条件,以使它永远不会返回false
时,循环变为无限并且无限地重复。
无限循环的一个例子:
这个循环永远不会结束,因为我从 1 开始递减i
的值,因此条件i <= 6
永远不会返回false
。
#include <iostream>
using namespace std;
int main(){
int i=1; while(i<=6) {
cout<<"Value of variable i is: "<<i<<endl; i--;
}
}
示例:使用while
循环显示数组元素
#include <iostream>
using namespace std;
int main(){
int arr[]={21,87,15,99, -12};
/* The array index starts with 0, the
* first element of array has 0 index
* and represented as arr[0]
*/
int i=0;
while(i<5){
cout<<arr[i]<<endl;
i++;
}
}
输出:
21
87
15
99
-12
C++ 中的do-while
循环
正如上一篇关于while
循环的教程中所讨论的,循环用于重复一个语句块,直到给定的循环条件返回false
。在本教程中,我们将看到do-while
循环。do-while
循环类似于while
循环,但它们之间存在差异:在while
循环中,首先计算条件,然后执行循环体内的语句,另一方面在do-while
循环中执行 - 首先执行,然后求值条件。
do-while
循环的语法
do
{
statement(s);
} while(condition);
do-while
循环如何工作?
首先,循环内的语句执行,然后条件得到求值,如果条件返回true
,则控制跳转到do
以进一步重复执行它,这会重复发生,直到条件返回false
。一旦条件返回false
,控制就会跳转到程序中do-while
之后的下一个语句。
C++ 中的do-while
循环示例
#include <iostream>
using namespace std;
int main(){
int num=1;
do{
cout<<"Value of num: "<<num<<endl;
num++;
}while(num<=6);
return 0;
}
输出:
Value of num: 1
Value of num: 2
Value of num: 3
Value of num: 4
Value of num: 5
Value of num: 6
示例:使用do-while
循环显示数组元素
这里我们有一个整数数组,它有四个元素。我们使用do-while
循环显示它的元素。
#include <iostream>
using namespace std;
int main(){
int arr[]={21,99,15,109};
/* Array index starts with 0, which
* means the first element of array
* is at index 0, arr[0]
*/
int i=0;
do{
cout<<arr[i]<<endl;
i++;
}while(i<4);
return 0;
}
输出:
21
99
15
109
C++ 中的continue
语句
原文: https://beginnersbook.com/2017/08/cpp-continue-statement/
在循环内使用continue
语句。每当在循环内遇到continue
语句时,控制流直接跳转到循环的开头以进行下一次迭代,跳过循环体内当前迭代的语句的执行。
continue
语句的语法
continue;
示例:for
循环中的continue
语句
正如你可以看到输出缺少值 3,但循环迭代num
值 0 到 6。这是因为我们在循环中设置了一个条件,这种情况下当num
值等于 3 时遇到语句。因此,对于此迭代,循环跳过cout
语句并开始下一次循环迭代。
#include <iostream>
using namespace std;
int main(){
for (int num=0; num<=6; num++) {
/* This means that when the value of
* num is equal to 3 this continue statement
* would be encountered, which would make the
* control to jump to the beginning of loop for
* next iteration, skipping the current iteration
*/
if (num==3) {
continue;
}
cout<<num<<" ";
}
return 0;
}
输出:
0 1 2 4 5 6
continue
语句的流程图
示例:在while
循环中使用continue
#include <iostream>
using namespace std;
int main(){
int j=6;
while (j >=0) {
if (j==4) {
j--;
continue;
}
cout<<"Value of j: "<<j<<endl;
j--;
}
return 0;
}
输出:
Value of j: 6
Value of j: 5
Value of j: 3
Value of j: 2
Value of j: 1
Value of j: 0
do-while
循环中continue
的示例
#include <iostream>
using namespace std;
int main(){
int j=4;
do {
if (j==7) {
j++;
continue;
}
cout<<"j is: "<<j<<endl;
j++;
}while(j<10);
return 0;
}
输出:
j is: 4
j is: 5
j is: 6
j is: 8
j is: 9
C++ 中的break
语句
break
语句用于以下两种情况:
a)使用break
语句立即退出循环。每当在循环内遇到break
语句时,控制流就会直接从循环中退出。它与if
语句一起使用,只能在循环内部使用(参见下面的示例),以便它仅在特定条件下发生。
b)用于switch-case
控制结构。通常,在switch case
中的所有情况都跟一个break
语句,以避免后续的情况(参见下面的例子)执行。无论何时在switch-case
块中遇到,控制流都从switch-case
体中出来。
break
语句的语法
break;
break
语句流程图
示例 - 在while
循环中使用break
语句
在下面的示例中,我们有一个从 10 到 200 运行的while
循环,但由于我们有一个在循环计数器,变量值达到 12 时遇到break
语句,循环终止并且控制流跳转到程序中循环体之后的下一个语句。
#include <iostream>
using namespace std;
int main(){
int num =10;
while(num<=200) {
cout<<"Value of num is: "<<num<<endl;
if (num==12) {
break;
}
num++;
}
cout<<"Hey, I'm out of the loop";
return 0;
}
输出:
Value of num is: 10
Value of num is: 11
Value of num is: 12
Hey, I'm out of the loop
示例:for
循环中的break
语句
#include <iostream>
using namespace std;
int main(){
int var;
for (var =200; var>=10; var --) {
cout<<"var: "<<var<<endl;
if (var==197) {
break;
}
}
cout<<"Hey, I'm out of the loop";
return 0;
}
输出:
var: 200
var: 199
var: 198
var: 197
Hey, I'm out of the loop
示例:switch-case
中的break
语句
#include <iostream>
using namespace std;
int main(){
int num=2;
switch (num) {
case 1: cout<<"Case 1 "<<endl;
break;
case 2: cout<<"Case 2 "<<endl;
break;
case 3: cout<<"Case 3 "<<endl;
break;
default: cout<<"Default "<<endl;
}
cout<<"Hey, I'm out of the switch case";
return 0;
}
输出:
Case 2
Hey, I'm out of the switch case
在这个例子中,我们在每个case
块之后都有break
语句,这是因为如果我们没有它,那么后续的case
块也会执行。没有break
的同一程序的输出将是:
Case 2
Case 3
Default
Hey, I'm out of the switch case
C++ 中的goto
语句
goto
语句用于将程序的控制转移到给定标签。 goto
语句的语法如下所示:
goto label_name;
程序结构:
label1:
...
...
goto label2;
...
..
label2:
...
在程序中我们有任意数量的goto
和label
语句,goto
语句后跟一个标签名称,每当遇到goto
语句时,程序的控制权就会跳转到goto
语句中指定的标签。
goto
语句几乎从不在任何开发中使用,因为它们很复杂,使得程序的可读性更低,更容易出错。代替goto
,你可以使用continue
和break
语句。
C++ 中goto
语句的示例
#include <iostream>
using namespace std;
int main(){
int num; cout<<"Enter a number: "; cin>>num;
if (num % 2==0){
goto print;
}
else {
cout<<"Odd Number";
}
print:
cout<<"Even Number";
return 0;
}
输出:
Enter a number: 42
Even Number
函数
C++ 中的函数
函数是用于执行特定任务的代码块,例如,假设您正在编写一个大型 C++ 程序,并且在该程序中,您希望多次执行特定任务,例如显示从 1 到 10 的值,为了做到这一点,你必须编写几行代码,每次显示值时都需要重复这些行。另一种方法是在函数内写入这些行,并在每次要显示值时调用该函数。这将使您的代码简单,可读和可重用。
函数的语法
return_type function_name (parameter_list)
{
//C++ Statements
}
让我们举一个简单的例子来理解这个概念。
一个简单的函数示例
#include <iostream>
using namespace std;
/* This function adds two integer values
* and returns the result
*/int
sum(int num1, int num2){
int num3 = num1+num2; return num3;
}
int main(){
//Calling the function
cout<<sum(1,99);
return 0;
}
输出:
100
同样的程序可以这样写:好吧,我正在编写这个程序,让你理解一个关于函数的重要术语,即函数声明。让我们先看看程序,然后在最后讨论函数声明,定义和函数调用。
#include <iostream>
using namespace std;
//Function declaration
int sum(int,int);
//Main function
int main(){
//Calling the function
cout<<sum(1,99);
return 0;
}
/* Function is defined after the main method
*/
int sum(int num1, int num2){
int num3 = num1+num2;
return num3;
}
函数声明:你已经看到我用两种方式编写了相同的程序,在第一个程序中我没有任何函数声明,在第二个程序中我在程序开头有函数声明。问题是,当您在程序中的main()
函数之前定义函数时,您不需要执行函数声明,但如果您在main()
函数之后编写函数,就像我们在第二个程序中那样,那么您需要先声明函数,否则会出现编译错误。
函数声明的语法:
return_type function_name(parameter_list);
注意:在提供parameter_list
时,您可以避免参数名称,就像我在上面的示例中所做的那样。我给了int sum(int,int);
而不是int sum(int num1,int num2);
。
函数定义:编写函数的全部称为定义函数。
函数定义语法:
return_type function_name(parameter_list) {
//Statements inside function
}
调用函数:我们可以像这样调用函数:
function_name(parameters);
现在我们已经理解了函数的工作原理,让我们看看 C++ 中的函数类型。
函数类型
我们在 C++中有两种类型的函数:
1)内置函数
2)用户定义的函数
1)内置函数
内置函数也称为库函数。我们不需要声明和定义这些函数,因为它们已经在 C++ 库中编写,例如iostream
,cmath
等。我们可以在需要时直接调用它们。
示例:C++ 内置函数示例
这里我们使用内置函数pow(x, y)
,它是x
的y
次幂。此函数在cmath
头文件中声明,因此我们使用#include
指令将该文件包含在我们的程序中。
#include <iostream>
#include <cmath>
using namespace std;
int main(){
/* Calling the built-in function
* pow(x, y) which is x to the power y
* We are directly calling this function
*/
cout<<pow(2,5);
return 0;
}
输出:
32
2)用户定义的函数
我们已经看过用户定义的函数,我们在本教程开头给出的示例是用户定义函数的示例。我们在程序中声明和编写的函数是用户定义的函数。让我们看另一个用户定义函数的例子。
用户定义的函数
#include <iostream>
#include <cmath>
using namespace std;
//Declaring the function sum
int sum(int,int);
int main(){
int x, y;
cout<<"enter first number: ";
cin>> x;
cout<<"enter second number: ";
cin>>y;
cout<<"Sum of these two :"<<sum(x,y);
return 0;
}
//Defining the function sum
int sum(int a, int b) {
int c = a+b;
return c;
}
输出:
enter first number: 22
enter second number: 19
Sum of these two :41
C++ 函数中的默认参数
原文: https://beginnersbook.com/2017/08/cpp-default-arguments/
在调用函数时不提供任何参数或仅提供少量参数时,将使用默认参数。在编译程序期间使用默认参数。例如,假设您有一个用户定义的函数sum
声明如下:int sum(int a=10, int b=20)
,现在在调用此函数时,您不提供任何参数,简称为sum()
;那么在这种情况下结果将是 30,编译器使用函数签名中声明的默认值 10 和 20。如果你只传递一个这样的参数:sum(80)
那么结果将是 100,使用传递的参数 80 作为第一个值,20 个从默认参数中获取。
示例:C++ 中的默认参数
#include <iostream>
using namespace std;
int sum(int a, int b=10, int c=20);
int main(){
/* In this case a value is passed as
* 1 and b and c values are taken from
* default arguments.
*/
cout<<sum(1)<<endl;
/* In this case a value is passed as
* 1 and b value as 2, value of c values is
* taken from default arguments.
*/
cout<<sum(1, 2)<<endl;
/* In this case all the three values are
* passed during function call, hence no
* default arguments have been used.
*/
cout<<sum(1, 2, 3)<<endl;
return 0;
}
int sum(int a, int b, int c){
int z;
z = a+b+c;
return z;
}
输出:
31
23
6
默认参数的规则
正如您在上面的示例中所看到的,我在函数声明期间仅为两个参数b
和c
分配了默认值。您可以为所有参数或仅选定的参数指定默认值,但在仅为某些参数指定默认值时,请记住以下规则:
如果为参数指定默认值,则必须为后续参数分配默认值,否则将出现编译错误。
例如:让我们看一些有效和无效的案例。
有效:以下函数声明有效:
int sum(int a=10, int b=20, int c=30);
int sum(int a, int b=20, int c=30);
int sum(int a, int b, int c=30);
无效:以下函数声明无效:
/* Since a has default value assigned, all the
* arguments after a (in this case b and c) must have
* default values assigned
*/
int sum(int a=10, int b, int c=30);
/* Since b has default value assigned, all the
* arguments after b (in this case c) must have
* default values assigned
*/
int sum(int a, int b=20, int c);
/* Since a has default value assigned, all the
* arguments after a (in this case b and c) must have
* default values assigned, b has default value but
* c doesn't have, thats why this is also invalid
*/
int sum(int a=10, int b=20, int c);
C++ 递归
函数调用自身的过程称为递归,相应的函数称为递归函数。理解递归的流行示例是阶乘函数。
阶乘函数: f(n) = n * f(n-1)
,基本条件:如果n <= 1
则f(n)= 1
。不要担心我们将讨论什么是基本条件,以及为什么它很重要。
在下图中。我已经证明了在函数达到基本条件之前,阶乘函数如何调用自身。
让我们用 C++ 程序解决问题。
C++ 递归示例:阶乘
#include <iostream>
using namespace std;
//Factorial function
int f(int n){
/* This is called the base condition, it is
* very important to specify the base condition
* in recursion, otherwise your program will throw
* stack overflow error.
*/
if (n <= 1)
return 1;
else
return n*f(n-1);
}
int main(){
int num;
cout<<"Enter a number: ";
cin>>num;
cout<<"Factorial of entered number: "<<f(num);
return 0;
}
输出:
Enter a number: 5
Factorial of entered number: 120
基本情况
在上面的程序中,您可以看到我在递归函数中提供了基本条件。条件是:
if (n <= 1)
return 1;
递归的目的是将问题分成较小的问题,直到达到基本条件。例如,在上述阶乘程序中,我通过调用较小的阶乘函数f(n-1)
来求解阶乘函数 f(n)
,这一直重复发生,直到n
值达到基本条件(f(1) = 1
)。如果未在递归函数中定义基本条件,则会出现堆栈溢出错误。
直接递归与间接递归
直接递归:当函数调用自身时,它被称为直接递归,我们上面看到的例子是直接递归示例。
间接递归:当函数调用另一个函数并且该函数调用这个函数时,这称为间接递归。例如:函数 A 调用函数 B,函数 B 调用函数 A。
C++ 中的间接递归示例
#include <iostream>
using namespace std;
int fa(int);
int fb(int);
int fa(int n){
if(n<=1)
return 1;
else
return n*fb(n-1);
}
int fb(int n){
if(n<=1)
return 1;
else
return n*fa(n-1);
}
int main(){
int num=5;
cout<<fa(num);
return 0;
}
输出:
120
基础
数组
C++ 中的数组
数组是存储在连续内存位置的类似项的集合。在编程中,有时一个简单的变量不足以容纳所有数据。例如,假设我们要存储 500 名学生的信息,这个任务有 500 个不同的变量是不可行的,我们可以定义一个大小为 500 的数组,可以保存所有学生的信息。
用 C++声明一个数组
有几种方法可以声明一个数组。
方法 1:
int arr[5];
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
方法 2:
int arr[] = {10, 20, 30, 40, 50};
方法 3:
int arr[5] = {10, 20, 30, 40, 50};
访问数组元素
数组索引以 0 开头,这意味着第一个数组元素位于索引 0,第二个数据元素位于索引 1,依此类推。我们可以使用此信息来显示数组元素。请参阅以下代码:
#include <iostream>
using namespace std;
int main(){
int arr[] = {11, 22, 33, 44, 55};
cout<<arr[0]<<endl;
cout<<arr[1]<<endl;
cout<<arr[2]<<endl;
cout<<arr[3]<<endl;
cout<<arr[4]<<endl;
return 0;
}
输出:
11
22
33
44
55
尽管此代码工作正常,但不建议显示此类数组的所有元素。当你想访问一个特定的数组元素时,这很好,但如果你想显示所有元素,那么你应该使用这样的循环:
#include <iostream>
using namespace std;
int main(){
int arr[] = {11, 22, 33, 44, 55};
int n=0;
while(n<=4){
cout<<arr[n]<<endl;
n++;
}
return 0;
}
C++ 中的多维数组
原文: https://beginnersbook.com/2017/08/cpp-multidimensional-arrays/
多维数组也称为数组的数组。多维数组中的数据以表格形式存储,如下图所示:
二维数组:
int arr[2][3];
该数组总共有2 * 3 = 6
个元素。
三维数组:
int arr[2][2][2];
该数组总共有2 * 2 * 2 = 8
个元素。
二维数组
让我们看看如何声明,初始化和访问二维数组的元素。
如何声明二维数组?
int myarray[2][3];
初始化:
我们可以通过多种方式初始化数组:
方法 1:
int arr[2][3] = {10, 11 ,12 ,20 ,21 , 22};
方法 2:
这种初始化方式是首选,因为您可以在此处显示行和列。
int arr[2][3] = {{10, 11 ,12} , {20 ,21 , 22}};
访问数组元素:
arr [0] [0]
- 第一个元素arr [0] [1]
- 第二个元素arr [0] [2]
- 第三个元素arr [1] [0]
- 第四个元素arr [1] [1]
- 第五个元素arr [1] [2]
- 第六个元素
示例:C++ 中的二维数组
#include <iostream>
using namespace std;
int main(){
int arr[2][3] = {{11, 22, 33}, {44, 55, 66}};
for(int i=0; i<2;i++){
for(int j=0; j<3; j++){
cout<<"arr["<<i<<"]["<<j<<"]: "<<arr[i][j]<<endl;
}
}
return 0;
}
输出:
arr[0][0]: 11
arr[0][1]: 22
arr[0][2]: 33
arr[1][0]: 44
arr[1][1]: 55
arr[1][2]: 66
三维数组
让我们看看如何声明,初始化和访问三维数组元素。
声明三维数组:
int myarray[2][3][2];
初始化:
我们可以通过多种方式初始化数组:
方法 1:
int arr[2][3][2] = {1, -1 ,2 ,-2 , 3 , -3, 4, -4, 5, -5, 6, -6};
方法 2:
这种初始化方式是首选,因为您可以在此处显示行和列。
int arr[2][3][2] = {
{ {1,-1}, {2, -2}, {3, -3}},
{ {4, -4}, {5, -5}, {6, -6}}
}
三维数组示例
#include <iostream>
using namespace std;
int main(){
// initializing the array
int arr[2][3][2] = {
{ {1,-1}, {2,-2}, {3,-3} },
{ {4,-4}, {5,-5}, {6,-6} }
};
// displaying array values
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 3; y++) {
for (int z = 0; z < 2; z++) {
cout<<arr[x][y][z]<<" ";
}
}
}
return 0;
}
输出:
1 -1 2 -2 3 -3 4 -4 5 -5 6 -6
看看这些相关的 C++ 程序:
在 C++ 中将数组传递给函数
原文: https://beginnersbook.com/2017/08/cpp-passing-array-to-function/
您可以将数组作为参数传递给函数,就像将变量作为参数传递一样。为了将数组传递给函数,您只需要在函数调用中提及数组名称,如下所示:
function_name(array_name);
示例:将数组传递给函数
在这个例子中,我们传递两个数组a
和b
到函数sum()
。此函数相加两个数组的相应元素并显示它们。
#include <iostream>
using namespace std;
/* This function adds the corresponding
* elements of both the arrays and
* displays it.
*/
void sum(int arr1[], int arr2[]){
int temp[5];
for(int i=0; i<5; i++){
temp[i] = arr1[i]+arr2[i];
cout<<temp[i]<<endl;
}
}
int main(){
int a[5] = {10, 20, 30, 40 ,50};
int b[5] = {1, 2, 3, 4, 5};
//Passing arrays to function
sum(a, b);
return 0;
}
输出:
11
22
33
44
55
示例 2:将多维数组传递给函数
在这个例子中,我们将多维数组传递给函数square
,该函数显示每个元素的平方。
#include <iostream>
#include <cmath>
using namespace std;
/* This method prints the square of each
* of the elements of multidimensional array
*/
void square(int arr[2][3]){
int temp;
for(int i=0; i<2; i++){
for(int j=0; j<3; j++){
temp = arr[i][j];
cout<<pow(temp, 2)<<endl;
}
}
}
int main(){
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
square(arr);
return 0;
}
输出:
1
4
9
16
25
36
C++ 中的字符串
字符串是由字符组成的单词,因此它们被称为字符序列。在 C++ 中,我们有两种方法来创建和使用字符串:1)通过创建char
数组并将它们视为字符串 2)通过创建string
对象
让我们先讨论这两种创建字符串的方法,然后我们会看到哪种方法更好,为什么。
1)字符数组 - 也称为 C 字符串
例 1:
一个简单例子,我们在声明期间初始化了char
数组。
#include <iostream>
using namespace std;
int main(){
char book[50] = "A Song of Ice and Fire";
cout<<book;
return 0;
}
输出:
A Song of Ice and Fire
示例 2:将用户输入作为字符串
这可以被视为读取用户输入的低效方法,为什么?因为当我们使用cin
读取用户输入字符串时,只有字符串的第一个单词存储在char
数组中而其余部分被忽略。cin
函数将字符串中的空格视为分隔符,并忽略其后的部分。
#include <iostream>
using namespace std;
int main(){
char book[50];
cout<<"Enter your favorite book name:";
//reading user input
cin>>book;
cout<<"You entered: "<<book;
return 0;
}
输出:
Enter your favorite book name:The Murder of Roger Ackroyd
You entered: The
你可以看到只有The
被捕获在book
中,空格之后的剩下部分被忽略。那怎么处理呢?那么,为此我们可以使用cin.get
函数,它读取用户输入的完整行。
示例 3:使用 cin.get
正确捕获用户输入字符串的方法
#include <iostream>
using namespace std;
int main(){
char book[50];
cout<<"Enter your favorite book name:";
//reading user input
cin.get(book, 50);
cout<<"You entered: "<<book;
return 0;
}
输出:
Enter your favorite book name:The Murder of Roger Ackroyd
You entered: The Murder of Roger Ackroyd
这种方法的缺点
1)char
数组的大小是固定的,这意味着通过它创建的字符串的大小是固定大小的,在运行时期间不能分配更多的内存。例如,假设您已创建一个大小为 10 的字符数组,并且用户输入大小为 15 的字符串,则最后五个字符将从字符串中截断。
另一方面,如果您创建一个更大的数组来容纳用户输入,那么如果用户输入很小并且数组比需要的大得多,则会浪费内存。
2)在这种方法中,你只能使用为数组创建的内置函数,它们对字符串操作没有多大帮助。
这些问题的解决方案是什么?
我们可以使用字符串对象创建字符串。让我们看看我们如何做到这一点。
C++ 中的string
对象
到目前为止我们已经看到了如何使用char
数组处理 C++ 中的字符串。让我们看看在 C++ 中处理字符串的另一种更好的方法 - 字符串对象。
#include<iostream>
using namespace std;
int main(){
// This is how we create string object
string str;
cout<<"Enter a String:";
/* This is used to get the user input
* and store it into str
*/
getline(cin,str);
cout<<"You entered: ";
cout<<str<<endl;
/* This function adds a character at
* the end of the string
*/ str.push_back('A');
cout<<"The string after push_back: "<<str<<endl;
/* This function deletes a character from
* the end of the string
*/
str.pop_back();
cout << "The string after pop_back: "<<str<<endl;
return 0;
}
输出:
Enter a String:XYZ
You entered: XYZ
The string after push_back: XYZA
The string after pop_back: XYZ
使用这种方法的好处是你不需要声明字符串的大小,大小是在运行时确定的,所以这是更好的内存管理方法。内存在运行时动态分配,因此不会浪费内存。
指针
C++ 中的指针
指针是 C++ 中的一个变量,它包含另一个变量的地址。它们的数据类型就像变量一样,例如整数类型指针可以保存整数变量的地址,字符类型指针可以保存char
变量的地址。
指针的语法
data_type *pointer_name;
如何声明指针?
/* This pointer p can hold the address of an integer
* variable, here p is a pointer and var is just a
* simple integer variable
*/
int *p, var
赋值
如上所述,整数类型指针可以保存另一个int
变量的地址。这里我们有一个整数变量var
和指针p
,它保存var
的地址。要将变量的地址赋值给指针,我们使用&
符号。
/* This is how you assign the address of another variable
* to the pointer
*/
p = &var;
如何使用它?
// This will print the address of variable var
cout<<&var;
/* This will also print the address of variable
* var because the pointer p holds the address of var
*/
cout<<p;
/* This will print the value of var, This is
* important, this is how we access the value of
* variable through pointer
*/
cout<<*p;
指针示例
让我们举一个简单的例子来理解我们上面讨论的内容。
#include <iostream>
using namespace std;
int main(){
//Pointer declaration
int *p, var=101;
//Assignment
p = &var;
cout<<"Address of var: "<<&var<<endl;
cout<<"Address of var: "<<p<<endl;
cout<<"Address of p: "<<&p<<endl;
cout<<"Value of var: "<<*p;
return 0;
}
输出:
Address of var: 0x7fff5dfffc0c
Address of var: 0x7fff5dfffc0c
Address of p: 0x7fff5dfffc10
Value of var: 101
指针和数组
在使用指针处理数组时,您需要注意一些事情。关于数组的第一个也是非常重要的注意事项是,数组名称单独表示数组的基地址,因此在将数组地址赋值给指针时不要使用符号(&
)。这样做:
正确:因为arr
代表数组的地址。
p = arr;
不正确:
p = &arr;
示例:使用指针遍历数组
#include <iostream>
using namespace std;
int main(){
//Pointer declaration
int *p;
//Array declaration
int arr[]={1, 2, 3, 4, 5, 6};
//Assignment
p = arr;
for(int i=0; i<6;i++){
cout<<*p<<endl;
//++ moves the pointer to next int position
p++;
}
return 0;
}
输出:
1
2
3
4
5
6
如何递增指针地址和指针的值?
当我们通过指针访问变量的值时,有时我们只需要增加或减少变量的值,或者我们可能需要将指针移动到下一个int
位置(就像我们在使用数组时一样)。 ++
运算符用于此目的。我们在上面看到的++
运算符的一个示例,我们通过使用++
运算符递增指针值来遍历数组。让我们看几个案例。
// Pointer moves to the next int position (as if it was an array)
p++;
// Pointer moves to the next int position (as if it was an array)
++p;
/* All the following three cases are same they increment the value
* of variable that the pointer p points.
*/
++*p;
++(*p);
++*(p);
C++ this
指针
this
指针保存当前对象的地址,简单来说,你可以说这个指针指向该类的当前对象。让我们举个例子来理解这个概念。
C++ 示例:this
指针
在这里你可以看到我们有两个数据成员num
和ch
。在成员函数setMyValues()
中,我们有两个与数据成员名称相同的局部变量。在这种情况下,如果要将局部变量值赋值给数据成员,那么除非使用this
指针,否则您将无法执行此操作,因为除非您使用this
,否则编译器将不知道您指的是对象的数据成员。这是必须使用this
指针的示例之一。
#include <iostream>
using namespace std;
class Demo {
private:
int num;
char ch;
public:
void setMyValues(int num, char ch){
this->num =num;
this->ch=ch;
}
void displayMyValues(){
cout<<num<<endl;
cout<<ch;
}
};
int main(){
Demo obj;
obj.setMyValues(100, 'A');
obj.displayMyValues();
return 0;
}
输出:
100
A
示例 2:使用this
指针进行函数链式调用
使用this
指针的另一个示例是返回当前对象的引用,以便您可以链式调用函数,这样您就可以一次调用当前对象的所有函数。在这个程序中需要注意的另一个要点是,我在第二个函数中增加了对象num
的值,你可以在输出中看到它实际上增加了我们在第一个函数调用中设置的值。这表明链接是顺序的,对对象的数据成员所做的更改将保留以进一步链式调用。
#include <iostream>
using namespace std;
class Demo {
private:
int num;
char ch;
public:
Demo &setNum(int num){
this->num =num;
return *this;
}
Demo &setCh(char ch){
this->num++;
this->ch =ch;
return *this;
}
void displayMyValues(){
cout<<num<<endl;
cout<<ch;
}
};
int main(){
Demo obj;
//Chaining calls
obj.setNum(100).setCh('A');
obj.displayMyValues();
return 0;
}
输出:
101
A
OOP
C++ 中的 OOP 概念
面向对象编程是一种通过使用对象将问题分解为更小问题来解决复杂问题的方法。在面向对象编程(通常称为 OOP)之前,程序是用过程语言编写的,它们只是一长串指令。另一方面,OOP 就是创建可以交互的对象,这使得在 OOP 中开发程序变得更容易,因为我们可以理解它们之间的关系。
面向对象编程(OOP)
在面向对象编程中,我们使用类和对象编写程序,利用 OOP 的特征,如抽象,封装,继承和多态。
类和对象
类就像数据成员和函数的蓝图,对象是类的实例。例如,假设我们有一个类 Car
,它有数据成员(变量),如speed
,weight
,price
,和函数,如gearChange()
,slowDown()
,brake()
等。现在让我们说我创建了一个名为FordFigo
的类的对象,它使用这些数据成员和函数,并为它们提供自己的值。同样,我们可以使用蓝图(类)创建任意数量的对象。
//Class name is Car
class Car
{
//Data members
char name[20];
int speed;
int weight;
public:
//Functions
void brake(){
}
void slowDown(){
}
};
int main()
{
//ford is an object
Car ford;
}
抽象
抽象是隐藏用户不相关细节的过程。例如,当您发送短信时,您只需键入消息,选择联系人并单击发送,手机会显示消息已发送,单击发送时背景中实际发生的情况对您是隐藏的,因为它对你不相关。
封装
封装是将数据和函数组合成像胶囊这样的单个单元的过程。这是为了避免从类外部访问私有数据成员。为了实现封装,我们将类的所有数据成员设为私有并创建公共函数,使用它们我们可以从这些数据成员获取值或为这些数据成员设置值。
继承
继承是一个特性,子类的对象使用该特性获取父类的属性。
#include <iostream>
using namespace std;
class ParentClass {
//data member
public:
int var1 =100;
};
class ChildClass: public ParentClass {
public:
int var2 = 500;
};
int main(void) {
ChildClass obj;
}
现在这个对象obj
可以使用ParentClass
的属性(例如变量var1
)。
多态
函数重载和运算符重载是多态的例子。多态是一种在不同情况下对象表现不同的特性。
在函数重载中,我们可以有多个函数,具有相同名称但不同数量,类型或顺序的参数。
多态实例
#include <iostream>
using namespace std;
class Sum {
public:
int add(int num1,int num2){
return num1 + num2;
}
int add(int num1, int num2, int num3){
return num1 + num2 + num3;
}
};
int main(void) {
//Object of class Sum
Sum obj;
//This will call the second add function
cout<<obj.add(10, 20, 30)<<endl;
//This will call the first add function
cout<<obj.add(11, 22);
return 0;
}
输出:
60
33
Hello World - 第一个 C++ 程序
在本指南中,我们将编写和理解** C++** 编程中的第一个程序。我们正在编写一个打印Hello World!
消息的简单 C++ 程序。让我们先看看程序,然后我们将详细讨论它的每一部分。
C++中的Hello World
程序
/*
* Multiple line
* comment
*/
#include<iostream>
//Single line comment
using namespace std;
//This is where the execution of program begins
int main()
{
// displays Hello World! on screen
cout<<"Hello World!";
return 0;
}
输出:
Hello World!
我们来讨论上述程序的每一部分。
1. 注释 - 您可以在上述程序中看到两种类型的注释
// This is a single line comment
/* This is a multiple line comment
* suitable for long comments
*/
顾名思义,注释只是程序员在代码开发过程中编写的文本。注释不会以任何方式影响您的程序逻辑,您可以在注释中编写任何您想要的内容,但它应该与代码相关并具有一些含义,以便当其他人查看您的代码时,该人只需阅读您的注释就应该了解您的代码。
例如:
/* This function adds two integer numbers
* and returns the result as an integer value
*/
int sum(int num1, int num2) {
return num1+num2;
}
现在,如果有人阅读我的注释,他或她只需阅读我的注释即可理解我在那里所做的事情。这提高了代码的可读性,当您与团队成员一起开展项目时,这将成为必不可少的方面。
2. #include <iostream>
- 此语句告诉编译器包含iostream
文件。该文件包含我们可以在程序中使用的预定义输入/输出函数。
3. using namespace std;
- 名称空间就像一个区域,我们有函数,变量等,它们的范围仅限于该特定区域。这里std
是一个命名空间名称,它告诉编译器查看所有变量,函数等的特定区域。我不会在这里详细讨论它,因为它可能会让你感到困惑。我在一个单独的教程中通过示例介绍了这个主题。按照给定顺序阅读教程,你会没事的。
4. int main()
- 顾名思义这是我们程序的主函数,程序的执行从这个函数开始,这里的int
是返回类型,它向编译器指示这个函数将返回一个整数值。这是我们在main
函数末尾放置return 0
语句的主要原因。
5. cout<<"Hello World!";
- cout
对象属于iostream
文件,此对象的目的是在屏幕上显示双引号之间的内容。这个对象也可以在屏幕上显示变量的值(不用担心,我们将在后面的教程中看到)。
6. return 0;
- 该语句从main()
函数返回值 0,表示main
函数执行成功。值 1 表示执行失败。
C++ 中的构造函数
构造函数是初始化类对象的类的特殊成员函数。构造函数名称与类名称相同,并且没有返回类型。让我们举一个简单的例子来理解构造函数的工作原理。
简单示例:如何在 C++ 中使用构造函数
阅读以下程序中的注释,以了解该程序的每个部分。
#include <iostream>
using namespace std;
class constructorDemo{
public:
int num;
char ch;
/* This is a default constructor of the
* class, do note that it's name is same as
* class name and it doesn't have return type.
*/
constructorDemo() {
num = 100; ch = 'A';
}
};
int main(){
/* This is how we create the object of class,
* I have given the object name as obj, you can
* give any name, just remember the syntax:
* class_name object_name;
*/
constructorDemo obj;
/* This is how we access data members using object
* we are just checking that the value we have
* initialized in constructor are reflecting or not.
*/
cout<<"num: "<<obj.num<<endl;
cout<<"ch: "<<obj.ch;
return 0;
}
输出:
num: 100
ch: A
构造函数与成员函数
现在我们知道什么是构造函数,让我们讨论构造函数与类的成员函数的不同之处。
1)构造函数没有返回类型。成员函数具有返回类型。
2)当我们创建类的对象时,会自动调用构造函数。需要使用类的对象显式调用成员函数。
3)当我们不在我们的类中创建任何构造函数时,C++ 编译器生成一个默认构造函数并将其插入到我们的代码中。这同样适用于成员函数。
这是编译器生成的默认构造函数的外观:
class XYZ
{
....
XYZ()
{
//Empty no code
}
};
C++ 中构造函数的类型
C++ 中有两种类型的构造函数。 1)默认构造函数 2)参数化构造函数
1)默认构造函数
默认构造函数没有任何参数(或参数)。
#include <iostream>
using namespace std;
class Website{
public:
//Default constructor
Website() {
cout<<"Welcome to BeginnersBook"<<endl;
}
};
int main(void){
/*creating two objects of class Website.
* This means that the default constructor
* should have been invoked twice.
*/
Website obj1;
Website obj2;
return 0;
}
输出:
Welcome to BeginnersBook
Welcome to BeginnersBook
如果未在类中指定任何构造函数,则编译器将在代码中插入没有代码(空体)的默认构造函数。
2)参数化构造函数
带参数的构造函数称为参数化构造函数。这些类型的构造函数允许我们在创建对象时传递参数。让我们看看他们的样子:
让我们假设类名是XYZ
。
默认构造函数:
XYZ() {
}
....
XYZ obj;
....
参数化构造函数:
XYZ(int a, int b) {
}
...
XYZ obj(10, 20);
例:
#include <iostream>
using namespace std;
class Add{
public:
//Parameterized constructor
Add(int num1, int num2) {
cout<<(num1+num2)<<endl;
}
};
int main(void){
/* One way of creating object. Also
* known as implicit call to the
* constructor
*/
Add obj1(10, 20);
/* Another way of creating object. This
* is known as explicit calling the
* constructor.
*/
Add obj2 = Add(50, 60);
return 0;
}
输出:
30
110
C++ 中的析构函数
析构函数是一个特殊的成员函数,与构造函数相反,与用于初始化对象的构造函数不同,析构函数销毁(或删除)对象。
析构函数语法:
~class_name()
{
//Some code
}
与构造函数类似,析构函数名称应与类名完全匹配。析构函数声明应始终以波形符(~
)符号开头,如上面的语法所示。
什么时候析构函数被调用?
在以下情况下,析构函数自动调用:
1)程序完成执行。
2)当包含局部变量的作用域({}
括号)结束时。
3)当你调用delete
运算符时。
析构函数示例
#include <iostream>
using namespace std;
class HelloWorld{
public:
//Constructor
HelloWorld(){
cout<<"Constructor is called"<<endl;
}
//Destructor
~HelloWorld(){
cout<<"Destructor is called"<<endl;
}
//Member function
void display(){
cout<<"Hello World!"<<endl;
}
};
int main(){
//Object created
HelloWorld obj;
//Member function called
obj.display();
return 0;
}
输出:
Constructor is called
Hello World!
Destructor is called
析构函数规则
1)名称应以波形符号(~
)开头,并且必须与类名匹配。
2)一个类中不能有多个析构函数。
3)与可以有参数的构造函数不同,析构函数不允许任何参数。
4)他们没有任何返回类型,就像构造函数一样。
5)当你没有在类中指定任何析构函数时,编译器会生成一个默认的析构函数并将其插入到代码中。
C++ 中的结构
结构是一种复合数据类型,包含不同类型的不同变量。例如,您要存储学生详细信息,例如学生姓名,学生卷数,学生年龄。你有两种方法可以做到这一点,一种方法是为每个数据创建不同的变量,但这种方法的缺点是,如果你想存储多个学生的细节,那么在这种情况下,为每个学生创建单独的一组变量是不可行的。
第二种是通过创建这样的结构来实现它,也是最好的方法:
struct Student
{
char stuName[30];
int stuRollNo;
int stuAge;
};
现在这三个成员组合起来就像一个单独的变量,你可以像这样创建结构变量:
structure_name variable_name
因此,如果您想要使用此结构保存两名学生的信息,那么您可以这样做:
Student s1, s2;
然后我可以像这样访问Student
结构的成员:
//Assigning name to first student
s1.stuName = "Ajeet";
//Assigning age to the second student
s2.stuAddr = 22;
同样,我可以为每个学生设置并获取结构的其他数据成员的值。让我们看一个完整的例子来把它们放在一起:
C++中的结构示例
#include <iostream>
using namespace std;
struct Student{
char stuName[30];
int stuRollNo;
int stuAge;
};
int main(){
Student s;
cout<<"Enter Student Name: ";
cin.getline(s.stuName, 30);
cout<<"ENter Student Roll No: ";
cin>>s.stuRollNo;
cout<<"Enter Student Age: ";
cin>>s.stuAge;
cout<<"Student Record:"<<endl;
cout<<"Name: "<<s.stuName<<endl;
cout<<"Roll No: "<<s.stuRollNo<<endl;
cout<<"Age: "<<s.stuAge;
return 0;
}
输出:
Enter Student Name: Negan
ENter Student Roll No: 4101003
Enter Student Age: 22
Student Record:
Name: Negan
Roll No: 4101003
Age: 22
C++ 中的结构和函数
原文: https://beginnersbook.com/2017/09/cpp-structure-and-function/
在之前的教程中,我们了解了结构,即对不同类型的变量进行分组的复合数据类型。在本教程中,我们将学习如何将结构作为参数传递给函数以及如何从函数返回结构。
如何将结构作为参数传递给函数
这里我们有一个函数printStudentInfo()
,它将结构Student
作为参数,并使用结构变量打印学生的详细信息。这里需要注意的重点是,您应该始终在函数声明之前声明结构,否则您将收到编译错误。
#include <iostream>
using namespace std;
struct Student{
char stuName[30];
int stuRollNo;
int stuAge;
};
void printStudentInfo(Student);
int main(){
Student s;
cout<<"Enter Student Name: ";
cin.getline(s.stuName, 30);
cout<<"Enter Student Roll No: ";
cin>>s.stuRollNo;
cout<<"Enter Student Age: ";
cin>>s.stuAge;
printStudentInfo(s);
return 0;
}
void printStudentInfo(Student s){
cout<<"Student Record:"<<endl;
cout<<"Name: "<<s.stuName<<endl;
cout<<"Roll No: "<<s.stuRollNo<<endl;
cout<<"Age: "<<s.stuAge;
}
输出:
Enter Student Name: Rick
Enter Student Roll No: 666123
Enter Student Age: 19
Student Record:
Name: Rick
Roll No: 666123
Age: 19
如何从函数返回结构
在这个例子中,我们有两个函数,一个从用户获取值,将它们赋值给结构成员并返回结构,另一个函数将该结构作为参数并打印细节。
#include <iostream>
using namespace std;
struct Student{
char stuName[30];
int stuRollNo;
int stuAge;
};
Student getStudentInfo();
void printStudentInfo(Student);
int main(){
Student s;
s = getStudentInfo();
printStudentInfo(s);
return 0;
}
/* This function prompt the user to input student
* details, stores them in structure members
* and returns the structure
*/
Student getStudentInfo(){
Student s;
cout<<"Enter Student Name: ";
cin.getline(s.stuName, 30);
cout<<"Enter Student Roll No: ";
cin>>s.stuRollNo;
cout<<"Enter Student Age: ";
cin>>s.stuAge;
return s;
}
void printStudentInfo(Student s){
cout<<"Student Record:"<<endl;
cout<<"Name: "<<s.stuName<<endl;
cout<<"Roll No: "<<s.stuRollNo<<endl;
cout<<"Age: "<<s.stuAge;
}
输出:
Enter Student Name: Tyrion lannister
Enter Student Roll No: 333901
Enter Student Age: 39
Student Record:
Name: Tyrion lannister
Roll No: 333901
Age: 39
C++ 中的枚举
枚举是用户定义的数据类型,我们为变量指定一组值,变量只能从一小组可能的值中取出一个。我们使用enum
关键字来定义枚举。
enum direction {East, West, North, South}dir;
这里枚举名称是只能取四个方向之一的指定值,声明末尾的dir
是枚举变量。
让我们举一个简单的例子来理解这一点:
这里我已经将值West
分配给枚举变量dir
,当我显示dir
的值时,它显示 1。这是因为默认情况下值从 0 开始递增,意思是东是 0,西是 1,北是 2,南是 3。
简单的枚举示例
#include<iostream>
using namespace std;
enum direction {East, West, North, South}dir;
int main()
{
dir = West;
cout<<dir;
return 0;
}
另一种声明枚举变量的方法
正如我们在上面的例子中看到的,我在枚举声明中声明了枚举变量dir
,还有另一种声明枚举变量的方法。
#include <iostream>
using namespace std;
enum direction {East, West, North, South};
int main(){
direction dir;
dir = South;
cout<<dir;
return 0;
}
输出:
3
为什么在 C++ 中使用enum
既然我们已经理解了什么是枚举以及如何在程序中使用它们,那么让我们讨论一下我们使用它们的原因:
只有在我们期望变量具有一组可能的值时才使用枚举,例如,我们有一个保存方向的dir
变量。由于我们有四个方向,这个变量可以取四个值中的任何一个,如果我们尝试为这个变量赋另一个随机值,它将抛出一个编译错误。这会增加编译时检查并避免通过传入无效常量而发生的错误。
经常使用它们的另一个重要位置是switch-case
语句,其中case
块期望的所有值都可以在枚举中定义。这样我们就可以确保我们在switch
括号中传递的enum
变量没有采用它不应该接受的任何随机值。
如何更改enum
的默认值
#include <iostream>
using namespace std;
enum direction {East=11, West=22, North=33, South=44};
int main(){
direction dir;
dir = South;
cout<<dir;
return 0;
}
输出:
44
C++ 中的继承
继承是面向对象编程系统(OOP)的特性之一,它允许子类获取父类的属性(数据成员)和函数(成员函数)。
什么是子类?
继承另一个类的类称为子类,它也称为派生类。
什么是父类?
被其他类继承的类称为父类,超类或基类。
继承语法
class parent_class
{
//Body of parent class
};
class child_class : access_modifier parent_class
{
//Body of child class
};
在 C++编程中使用继承有什么好处
继承的主要优点是代码可重用性和可读性。当子类继承父类的属性和函数时,我们不需要在子类中再次编写相同的代码。这使得重用代码变得更容易,使我们编写更少的代码,代码变得更具可读性。
让我们来看一个现实生活中的例子来理解这一点:让我们假设Human
是一个具有height
,weight
,color
等属性的类,以及诸如eat()
,sleep()
,dream()
,work()
等函数。
现在我们要创建Male
和Female
类,这些类是不同的,但由于男性和女性都是人类,他们共享一些共同的属性和行为(函数),所以他们可以继承Human
类,其余的那些属性和函数可以单独写在它们的类中。
这种方法使我们编写更少的代码,因为这两个类从基类继承了几个属性和函数,因此我们不需要重写它们。此外,这使得更容易阅读代码。
继承示例
在我们讨论继承类型之前,让我们举个例子:
这里我们有两个类Teacher
和MathTeacher
,MathTeacher
类继承了Teacher
类,这意味着Teacher
是一个父类,MathTeacher
是一个子类。子类可以使用父类的属性collegeName
。
另一个要注意的重点是,当我们创建子类的对象时,它调用子类的构造函数,子类构造函数自动调用基类的构造函数。
#include <iostream>
using namespace std;
class Teacher {
public:
Teacher(){
cout<<"Hey Guys, I am a teacher"<<endl;
}
string collegeName = "Beginnersbook";
};
//This class inherits Teacher class
class MathTeacher: public Teacher {
public:
MathTeacher(){
cout<<"I am a Math Teacher"<<endl;
}
string mainSub = "Math";
string name = "Negan";
};
int main() {
MathTeacher obj;
cout<<"Name: "<<obj.name<<endl;
cout<<"College Name: "<<obj.collegeName<<endl;
cout<<"Main Subject: "<<obj.mainSub<<endl;
return 0;
}
输出:
Hey Guys, I am a teacher
I am a Math Teacher
Name: Negan
College Name: Beginnersbook
Main Subject: Math
C++ 中的继承类型
1)单一继承
2)多级继承
3)多重继承
4)分层继承
5)混合继承
单继承
在单继承中,一个类完全继承一个类。
例如:假设我们有A
类和B
类.
B inherits A
单一继承的例子:
#include <iostream>
using namespace std;
class A {
public:
A(){
cout<<"Constructor of A class"<<endl;
}
};
class B: public A {
public:
B(){
cout<<"Constructor of B class";
}
};
int main() {
//Creating object of class B
B obj;
return 0;
}
输出:
Constructor of A class
Constructor of B class
2)多级继承
在这种类型的继承中,一个类继承另一个子类。
C inherits B and B inherits A
多级继承示例:
#include <iostream>
using namespace std;
class A {
public:
A(){
cout<<"Constructor of A class"<<endl;
}
};
class B: public A {
public:
B(){
cout<<"Constructor of B class"<<endl;
}
};
class C: public B {
public:
C(){
cout<<"Constructor of C class"<<endl;
}
};
int main() {
//Creating object of class C
C obj;
return 0;
}
输出:
Constructor of A class
Constructor of B class
Constructor of C class
多重继承
在多继承中,类可以继承多个类。这意味着在这种类型的继承中,单个子类可以具有多个父类。
例如:
C inherits A and B both
多重继承的例子:
#include <iostream>
using namespace std;
class A {
public:
A(){
cout<<"Constructor of A class"<<endl;
}
};
class B {
public:
B(){
cout<<"Constructor of B class"<<endl;
}
};
class C: public A, public B {
public:
C(){
cout<<"Constructor of C class"<<endl;
}
};
int main() {
//Creating object of class C
C obj;
return 0;
}
Constructor of A class
Constructor of B class
Constructor of C class
4)分层继承
在这种类型的继承中,一个父类具有多个子类。例如:
Class B and C inherits class A
分层继承的例子:
#include <iostream>
using namespace std;
class A {
public:
A(){
cout<<"Constructor of A class"<<endl;
}
};
class B: public A {
public:
B(){
cout<<"Constructor of B class"<<endl;
}
};
class C: public A{
public:
C(){
cout<<"Constructor of C class"<<endl;
}
};
int main() {
//Creating object of class C
C obj;
return 0;
}
输出:
Constructor of A class
Constructor of C class
5)混合继承
混合继承是多种继承类型的组合。例如,遵循多重和分层继承的子类和父类关系都可以称为混合继承。
C++ 中的多态
多态是 OOP 的一个特征,它允许对象在不同条件下表现不同。在 C++ 中,我们有两种类型的多态:
1)编译时多态 - 这也称为静态(或早期)绑定。
2)运行时多态 - 这也称为动态(或晚期)绑定。
1)编译时多态
函数重载和运算符重载是编译时多态的完美例子。
编译时多态示例
在这个例子中,我们有两个具有相同名称但参数数量不同的函数。根据我们在函数调用期间传递的参数确定要调用哪个函数,这就是为什么它被视为多态的一个例子,因为在不同的条件下输出是不同的。因为,在编译期间确定调用,这就是为什么它被称为编译时多态。
#include <iostream>
using namespace std;
class Add {
public:
int sum(int num1, int num2){
return num1+num2;
}
int sum(int num1, int num2, int num3){
return num1+num2+num3;
}
};
int main() {
Add obj;
//This will call the first function
cout<<"输出: "<<obj.sum(10, 20)<<endl;
//This will call the second function
cout<<"输出: "<<obj.sum(11, 22, 33);
return 0;
}
输出:
输出: 30
输出: 66
2)运行时多态
函数覆盖是运行时多态的一个例子。
函数覆盖:当子类声明一个已存在于父类中的方法时,这称为函数覆盖,这里子类覆盖父类。
在函数覆盖的情况下,我们有两个相同函数的定义,一个是父类,一个是子类。在运行时确定对函数的调用,以决定调用函数的哪个定义,这就是它被称为运行时多态的原因。
运行时多态的例子
#include <iostream>
using namespace std;
class A {
public:
void disp(){
cout<<"Super Class Function"<<endl;
}
};
class B: public A{
public:
void disp(){
cout<<"Sub Class Function";
}
};
int main() {
//Parent class object
A obj;
obj.disp();
//Child class object
B obj2;
obj2.disp();
return 0;
}
输出:
Super Class Function
Sub Class Function
C++ 中的函数重载
原文: https://beginnersbook.com/2017/08/cpp-function-overloading/
函数重载是 C++ 编程的一个特性,它允许我们有多个具有相同名称但不同参数列表的函数,当我说参数列表时,它表示参数的数据类型和顺序,例如函数myfuncn(int a, float b)
的参数列表是(int, float)
,它与函数myfuncn(float a, int b)
参数列表(float, int)
不同。函数重载是编译时多态。
现在我们知道什么是参数列表,让我们看一下重载规则:我们可以在同一范围内拥有以下函数。
sum(int num1, int num2)
sum(int num1, int num2, int num3)
sum(int num1, double num2)
记住这条规则的最简单方法是参数应符合以下任何一个或多个条件,它们应具有不同的类型,数量或顺序的参数。
例如:
这两个函数有不同的参数类型:
sum(int num1, int num2)
sum(double num1, double num2)
这两个的参数数量不同:
sum(int num1, int num2)
sum(int num1, int num2, int num3)
这两个有不同的参数顺序:
sum(int num1, double num2)
sum(double num1, int num2)
以上三种情况都是有效的重载情况。我们可以有任意数量的函数,只需记住参数列表应该是不同的。例如:
int sum(int, int)
double sum(int, int)
由于参数列表相同,因此不允许这样做。尽管它们具有不同的返回类型,但它无效。
函数重载示例
让我们举一个例子来理解 C++ 中的函数重载。
#include <iostream>
using namespace std;
class Addition {
public:
int sum(int num1,int num2) {
return num1+num2;
}
int sum(int num1,int num2, int num3) {
return num1+num2+num3;
}
};
int main(void) {
Addition obj;
cout<<obj.sum(20, 15)<<endl;
cout<<obj.sum(81, 100, 10);
return 0;
}
输出:
35
191
函数重载例 2
正如我在本指南开头所提到的,具有不同返回类型和相同参数列表的函数不能重载。但是,如果函数具有不同的参数列表,则它们可以具有相同或不同的返回类型,以便有资格进行重载。简而言之,函数的返回类型在函数重载中不起任何作用。重要的是函数的参数列表。
#include <iostream>
using namespace std;
class DemoClass {
public:
int demoFunction(int i) {
return i;
}
double demoFunction(double d) {
return d;
}
};
int main(void) {
DemoClass obj;
cout<<obj.demoFunction(100)<<endl;
cout<<obj.demoFunction(5005.516);
return 0;
}
输出:
100
5006.52
函数重载的优点
函数重载的主要优点是提高代码可读性并允许代码可重用性。在示例 1 中,我们已经看到我们如何能够为具有不同参数的相同任务(添加)提供多个函数,这允许我们相加两个整数以及三个整数,如果我们希望我们可以创建一些具有相同名称和四个或五个参数的函数。
想象一下,如果我们没有函数重载,我们要么只能相加两个整数,要么为同一个任务添加编写不同的名称函数,这会降低代码的可读性和可重用性。
C++ 函数覆盖
原文: https://beginnersbook.com/2017/09/cpp-function-overriding/
函数覆盖允许我们在子类中具有已存在于父类中的相同函数。子类继承父类的数据成员和成员函数,但是当您想要覆盖覆盖中的函数时,您可以使用函数覆盖。这就像在子类中创建旧函数的新版本一样。
函数覆盖示例
要覆盖函数,您必须在子类中具有相同的签名。签名是指数据类型和参数序列。这里我们在父函数中没有任何参数,所以我们没有在子函数中使用任何参数。
#include <iostream>
using namespace std;
class BaseClass {
public:
void disp(){
cout<<"Function of Parent Class";
}
};
class DerivedClass: public BaseClass{
public:
void disp() {
cout<<"Function of Child Class";
}
};
int main() {
DerivedClass obj = DerivedClass();
obj.disp();
return 0;
}
输出:
Function of Child Class
注意:在函数覆盖中,父类中的函数被称为被覆盖函数,子类中的函数称为覆盖函数。
如何从子类调用被覆盖函数
正如我们在上面看到的那样,当我们调用函数(涉及覆盖)时,会调用子类函数(覆盖函数)。如果要通过使用子类的对象来调用被覆盖的函数,该怎么办?您可以通过创建子类对象,并使父类的引用指向它来实现。让我们举个例子来理解它。
#include <iostream>
using namespace std;
class BaseClass {
public:
void disp(){
cout<<"Function of Parent Class";
}
};
class DerivedClass: public BaseClass{
public:
void disp() {
cout<<"Function of Child Class";
}
};
int main() {
/* Reference of base class pointing to
* the object of child class.
*/
BaseClass obj = DerivedClass();
obj.disp();
return 0;
}
输出:
Function of Parent Class
如果你想从覆盖函数调用被覆盖的函数,那么你可以这样做:
parent_class_name::function_name
要在上面的例子中执行此操作,我们可以在子类的disp()
函数中编写以下语句:
BaseClass::disp();
C++ 中的虚函数:运行时多态
原文: https://beginnersbook.com/2017/09/cpp-virtual-functions-runtime-polymorphism/
在本指南中,我们将看到什么是虚函数以及我们使用它们的原因。当我们在一个类中将一个函数声明为虚函数时,所有覆盖此函数的子类默认情况下的函数实现为虚函数(无论它们是否标记为虚拟)。
为什么我们声明一个虚函数?
让编译器知道需要在运行时解析对此函数的调用(也称为晚期绑定和动态链接),以便确定对象类型并且调用函数的正确版本。
让我们举个例子来理解当我们不将覆盖函数标记为虚拟时会发生什么。
示例 1:覆盖非虚函数
在这里看到问题。即使我们指向子类的实例(对象)的父类指针,也会调用该函数的父类版本。
您可能在想我为什么创建指针,我可以简单地创建子类的对象,如下所示:Dog obj;
并将Dog
实例分配给它。好吧,在这个例子中我只有一个子类,但是当我们有一个包含多个子类的大项目时,不建议单独创建子类的对象,因为它增加了复杂性并且代码容易出错。在此示例之后更加清晰。
#include<iostream>
using namespace std;
//Parent class or super class or base class
class Animal{
public:
void animalSound(){
cout<<"This is a generic Function";
}
};
//child class or sub class or derived class
class Dog : public Animal{
public:
void animalSound(){
cout<<"Woof";
}
};
int main(){
Animal *obj;
obj = new Dog();
obj->animalSound();
return 0;
}
输出:
This is a generic Function
示例 2:使用虚函数
在这种情况下,输出是Woof
,这是我们所期望的。在这种情况下会发生什么?由于我们将函数animalSound()
标记为虚拟,因此在运行时解析对函数的调用,编译器在运行时确定对象的类型并调用适当的函数。
#include<iostream>
using namespace std;
//Parent class or super class or base class
class Animal{
public:
virtual void animalSound(){
cout<<"This is a generic Function";
}
};
//child class or sub class or derived class
class Dog : public Animal{
public:
void animalSound(){
cout<<"Woof";
}
};
int main(){
Animal *obj;
obj = new Dog();
obj->animalSound();
return 0;
}
输出:
Woof
C++ 中的变量
变量是与可以更改的值相关联的名称。例如,当我写int num=20;
时,变量名是num
,它与值 20 相关联,int
是数据类型,表示该变量可以保存整数值。我们将在下一个教程中介绍数据类型。在本教程中,我们将讨论变量。
在 C++ 中声明变量的语法
data_type variable1_name = value1, variable2_name = value2;
例如:
int num1=20, num2=100;
我们也可以这样写:
int num1,num2;
num1=20;
num2=100;
变量的类型
变量可以根据其数据类型进行分类。例如,在上面的例子中,我们看到了整数类型变量。以下是 C++ 中可用的变量类型。
int
:这些类型的变量保存整数值。
char
:保存字符值,如'c'
,'F'
,'B'
,'p'
,'q'
等。
bool
:保存布尔值为true
或false
。
double
:双精度浮点值。
float
:单精度浮点值。
基于作用域的变量类型
在进一步讨论之前,先讨论什么是作用域。当我们讨论 Hello World 程序时,我们在程序中看到了这样的大括号:
int main {
//Some code
}
在这些花括号内声明的任何变量都限制在这些花括号中,如果你在main()
函数中声明一个变量并尝试在main()
函数之外使用该变量,那么你将得到编译错误。
现在我们已经理解了什么是作用域。让我们根据作用域转向变量类型。
- 全局变量
- 局部变量
全局变量
在任何函数之外声明的变量(包括main
)也称为全局变量。全局变量拥有整个程序中的作用域,它们可以在程序的任何地方,主函数,用户定义的函数中的任何地方访问。
让我们举个例子来理解它:
全局变量示例
这里我们有一个全局变量myVar
,它在main
之外声明。我们在main()
函数中访问了变量两次而没有任何问题。
#include <iostream>
using namespace std;
// This is a global variable
char myVar = 'A';
int main()
{
cout <<"Value of myVar: "<< myVar<<endl;
myVar='Z';
cout <<"Value of myVar: "<< myVar;
return 0;
}
输出:
Value of myVar: A
Value of myVar: Z
局部变量
局部变量在任何用户定义函数,主函数,循环或任何控制语句(if
,if-else
等)的大括号内声明,并且其作用域限制在这些大括号内。
局部变量的例子
#include <iostream>
using namespace std;
char myFuncn() {
// This is a local variable
char myVar = 'A';
}
int main()
{
cout <<"Value of myVar: "<< myVar<<endl;
myVar='Z';
cout <<"Value of myVar: "<< myVar;
return 0;
}
输出:
编译时错误,因为我们试图在其作用域之外访问变量myVar
。 myVar
的作用域仅限于这些括号内的函数体myFuncn()
。
全局变量和局部变量可以在 C++ 中具有相同的名称吗?
让我们看一个具有相同名称的全局变量和局部变量的示例。
#include <iostream>
using namespace std;
// This is a global variable
char myVar = 'A';
char myFuncn() {
// This is a local variable
char myVar = 'B';
return myVar;
}
int main()
{
cout <<"Funcn call: "<< myFuncn()<<endl;
cout <<"Value of myVar: "<< myVar<<endl;
myVar='Z';
cout <<"Funcn call: "<< myFuncn()<<endl;
cout <<"Value of myVar: "<< myVar<<endl;
return 0;
}
输出:
Funcn call: B
Value of myVar: A
Funcn call: B
Value of myVar: Z
正如您所看到的,当我在main
函数中更改myVar
的值时,它只更改了全局变量myVar
的值,因为局部变量myVar
作用域仅限于函数myFuncn()
。
C++ 封装
封装是将数据成员和函数组合在一个称为类的单个单元中的过程。这是为了防止直接访问数据,通过类的函数提供对它们的访问。它是面向对象编程(OOP)的流行特性之一,它有助于数据隐藏。
如何在类上实现封装
为此:
1)将所有数据成员设为私有。
2)为每个数据成员创建公共设置器和获取器函数,使设置器设置数据成员的值,获取器获取数据成员的值。
让我们在一个示例程序中看到这个:
C++ 中的封装示例
这里我们有两个数据成员num
和ch
,我们已将它们声明为私有,因此它们在类外无法访问,这样我们就隐藏了数据。获取和设置这些数据成员的值的唯一方法是通过公共设置器和获取器函数。
#include<iostream>
using namespace std;
class ExampleEncap{
private:
/* Since we have marked these data members private,
* any entity outside this class cannot access these
* data members directly, they have to use getter and
* setter functions.
*/
int num;
char ch;
public:
/* Getter functions to get the value of data members.
* Since these functions are public, they can be accessed
* outside the class, thus provide the access to data members
* through them
*/
int getNum() const {
return num;
}
char getCh() const {
return ch;
}
/* Setter functions, they are called for assigning the values
* to the private data members.
*/
void setNum(int num) {
this->num = num;
}
void setCh(char ch) {
this->ch = ch;
}
};
int main(){
ExampleEncap obj;
obj.setNum(100);
obj.setCh('A');
cout<<obj.getNum()<<endl;
cout<<obj.getCh()<<endl;
return 0;
}
输出:
100
A
C++ 中的抽象
原文: https://beginnersbook.com/2017/09/abstraction-in-c-with-example/
抽象是面向对象编程的功能之一,您只需向用户显示相关详细信息并隐藏不相关的详细信息。例如,当您向某人发送电子邮件时,您只需单击“发送”即可获得成功消息,单击“发送”时实际发生的情况,数据通过网络传输给收件人的方式对您来说是隐藏的(因为它与您无关) 。
让我们看看如何使用访问说明符在 C++ 程序中实现:
抽象示例
#include <iostream>
using namespace std;
class AbstractionExample{
private:
/* By making these data members private, I have
* hidden them from outside world.
* These data members are not accessible outside
* the class. The only way to set and get their
* values is through the public functions.
*/
int num;
char ch;
public:
void setMyValues(int n, char c) {
num = n; ch = c;
}
void getMyValues() {
cout<<"Numbers is: "<<num<< endl;
cout<<"Char is: "<<ch<<endl;
}
};
int main(){
AbstractionExample obj;
obj.setMyValues(100, 'X');
obj.getMyValues();
return 0;
}
输出:
Numbers is: 100
Char is: X
数据抽象的优势
使用此功能的主要优点是,当代码发展并且您需要在代码中进行一些调整时,您只需要修改已将成员声明为私有的高级类。由于没有类直接访问这些数据成员,因此您无需更改低级别(用户级别)类代码。
想象一下,如果您将这些数据成员公开,如果在某些时候您想要更改代码,则必须对直接访问成员的所有类进行必要的调整。
数据抽象的其他优点是:
1)通过使数据私有化并避免可能破坏数据的用户级错误,使应用安全。
2)这避免了代码重复并增加了代码的可重用性。
C++ 中的接口:抽象类
在 C++ 中,我们互换使用术语抽象类和接口。具有纯虚函数的类称为抽象类。例如,以下函数是纯虚函数:
virtual void fun() = 0;
纯虚函数用虚拟关键字标记,签名后有= 0
。您可以将此函数称为抽象函数,因为它没有正文。派生类必须为父类的所有纯虚函数提供实现,否则默认情况下它将成为抽象类。
为什么我们需要一个抽象类?
让我们借助现实生活中的例子来理解这一点。让我们说我们有一个类Animal
,它会睡眠,发出声音等等。现在我只考虑这两个行为并创建一个具有两个函数sound()
和sleeping()
的类Animal
。
现在,我们知道动物的声音是不同的,猫说“喵”,狗说“汪”。那么我在Animal
类中为函数sound()
提供了什么实现?这样做的唯一和正确的方法是使这个函数纯粹抽象,这样我就不需要在Animal
类中给出实现但是所有继承Animal
的类必须为此函数提供实现。这样我确保所有动物都有声音,但它们有独特的声音。
可以在 C++ 程序中编写相同的示例,如下所示:
抽象类示例
#include<iostream>
using namespace std;
class Animal{
public:
//Pure Virtual Function
virtual void sound() = 0;
//Normal member Function
void sleeping() {
cout<<"Sleeping";
}
};
class Dog: public Animal{
public:
void sound() {
cout<<"Woof"<<endl;
}
};
int main(){
Dog obj;
obj.sound();
obj.sleeping();
return 0;
}
抽象类规则
1)我们已经看到任何具有纯虚函数的类都是抽象类。
2)我们无法创建抽象类的实例。例如:如果我在上面的程序中写了这行Animal obj;
,就会导致编译错误。
3)我们可以创建指向子类的实例的抽象基类的指针和引用。例如,这是有效的:
Animal *obj = new Dog();
obj->sound();
4)抽象类可以有构造函数。
5)如果派生类没有实现父类的纯虚函数,则派生类变为抽象类。
从 C++ 中的函数传递和返回对象
原文: https://beginnersbook.com/2017/09/cpp-pass-and-return-object-from-a-function/
在本教程中,我们将了解如何将对象作为参数传递给函数以及如何从函数返回对象。
将对象传递给函数
可以将对象传递给函数,就像我们将结构传递给函数一样。在A
类中,我们有一个函数disp()
,我们在其中传递类A
的对象。类似地,我们可以将一个类的对象传递给不同类的函数。
#include <iostream>
using namespace std;
class A {
public:
int n=100;
char ch='A';
void disp(A a){
cout<<a.n<<endl;
cout<<a.ch<<endl;
}
};
int main() {
A obj;
obj.disp(obj);
return 0;
}
输出:
100
A
从函数返回对象
在这个例子中,我们有两个函数,函数input()
返回Student
对象,disp()
将Student
对象作为参数。
#include <iostream>
using namespace std;
class Student {
public:
int stuId;
int stuAge;
string stuName;
/* In this function we are returning the
* Student object.
*/
Student input(int n, int a, string s){
Student obj;
obj.stuId = n;
obj.stuAge = a;
obj.stuName = s;
return obj;
}
/* In this function we are passing object
* as an argument.
*/
void disp(Student obj){
cout<<"Name: "<<obj.stuName<<endl;
cout<<"Id: "<<obj.stuId<<endl;
cout<<"Age: "<<obj.stuAge<<endl;
}
};
int main() {
Student s;
s = s.input(1001, 29, "Negan");
s.disp(s);
return 0;
}
输出:
Name: Negan
Id: 1001
Age: 29
C++ 中的友元类和友元函数
原文: https://beginnersbook.com/2017/09/friend-class-and-friend-functions/
我们知道一个类无法访问其他类的私有成员。类似地,不继承另一个类的类不能访问其受保护的成员。
友元类:
友元类是一个类,可以访问被声明为友元的类的私有成员和受保护成员。当我们想要允许特定类访问类的私有成员和受保护成员时,这是必需的。
函数类示例
在这个例子中,我们有两个类XYZ
和ABC
。 XYZ
类有两个私有数据成员ch
和num
,这个类将ABC
声明为友元类。这意味着ABC
可以访问XYZ
的私有成员,在ABC
类的函数disp()
访问私有成员num
和ch
的示例中也证明了这一点。在这个例子中,我们将对象作为参数传递给函数。
#include <iostream>
using namespace std;
class XYZ {
private:
char ch='A';
int num = 11;
public:
/* This statement would make class ABC
* a friend class of XYZ, this means that
* ABC can access the private and protected
* members of XYZ class.
*/
friend class ABC;
};
class ABC {
public:
void disp(XYZ obj){
cout<<obj.ch<<endl;
cout<<obj.num<<endl;
}
};
int main() {
ABC obj;
XYZ obj2;
obj.disp(obj2);
return 0;
}
输出:
A
11
友元函数:
与友元类相似,此函数可以访问另一个类的私有和受保护成员。全局函数也可以声明为友元,如下例所示:
友元函数示例
#include <iostream>
using namespace std;
class XYZ {
private:
int num=100;
char ch='Z';
public:
friend void disp(XYZ obj);
};
//Global Function
void disp(XYZ obj){
cout<<obj.num<<endl;
cout<<obj.ch<<endl;
}
int main() {
XYZ obj;
disp(obj);
return 0;
}
输出:
100
Z
C++ 中的数据类型
数据类型定义变量可以容纳的数据类型,例如整数变量可以保存整数数据,字符类型变量可以保存字符数据等。
C++ 中的数据类型分为三组:内置,用户定义和派生。
内置数据类型
char
:用于字符。大小 1 个字节。
char ch = 'A';
int
:用于整数。大小 2 个字节。
int num = 100;
float
:用于单精度浮点数。大小 4 个字节。
float num = 123.78987;
double
:用于双精度浮点数。大小为 8 个字节。
double num = 10098.98899;
bool
:用于布尔,真或者假。
bool b = true;
wchar_t
:宽字符。应该避免这种情况,因为它的大小是实现定义的并且不可靠。
用户定义的数据类型
我们在 C++中有三种类型的用户定义数据类型。
struct
union
enum
我在单独的教程中详细介绍了它们。现在只记得它们属于用户定义的数据类型。
C++ 中的派生数据类型
我们在 C++ 中有三种派生数据类型
- 数组
- 函数
- 指针
它们是 C++ 的广泛主题,我在单独的教程中介绍了它们。按照给定顺序阅读教程,你会没事的。
C++ 中的运算符
运算符代表一个行为。例如,+
是表示加法的运算符。运算符处理两个或多个操作数并生成输出。例如3 + 4 + 5
,这里+
运算符在三个操作数上工作并产生 12 作为输出。
C++ 中的运算符类型
1)基本算术运算符
2)赋值运算符
3)自增和自减运算符
4)逻辑运算符
5)比较(关系)运算符
6)位运算符
7)三元运算符
1)基本算术运算符
基本算术运算符为:+ - * / %
+
用于加法。-
用于减法。*
用于乘法。/
用于除法。%
用于模数。
注:模运算符返回余数,例如20%5
将返回 0。
算术运算符的例子
#include <iostream>
using namespace std;
int main(){
int num1 = 240;
int num2 = 40;
cout<<"num1 + num2: "<<(num1 + num2)<<endl;
cout<<"num1 - num2: "<<(num1 - num2)<<endl;
cout<<"num1 * num2: "<<(num1 * num2)<<endl;
cout<<"num1 / num2: "<<(num1 / num2)<<endl;
cout<<"num1 % num2: "<<(num1 % num2)<<endl;
return 0;
}
输出:
num1 + num2: 280
num1 - num2: 200
num1 * num2: 9600
num1 / num2: 6
num1 % num2: 0
2)赋值运算符
C++ 中的赋值运算符是:= += -= *= /= %=
num2 = num1
将变量num1
的值赋给变量num2
。num2 += num1
等于num2 = num2 + num1
num2 -= num1
等于num2 = num2 - num1
num2 *= num1
等于num2 = num2 * num1
num2 /= num1
等于num2 = num2 / num1
num2 %= num1
等于num2 = num2 % num1
赋值运算符的示例
#include <iostream>
using namespace std;
int main(){
int num1 = 240;
int num2 = 40;
num2 = num1;
cout<<"= 输出: "<<num2<<endl;
num2 += num1;
cout<<"+= 输出: "<<num2<<endl;
num2 -= num1;
cout<<"-= 输出: "<<num2<<endl;
num2 *= num1;
cout<<"*= 输出: "<<num2<<endl;
num2 /= num1;
cout<<"/= 输出: "<<num2<<endl;
num2 %= num1;
cout<<"%= 输出: "<<num2<<endl;
return 0;
}
输出:
= 输出: 240
+= 输出: 480
-= 输出: 240
*= 输出: 57600
/= 输出: 240
%= 输出: 0
3)自增和自减运算符
++
和--
:
num++
相当于num = num + 1;
num--
相当于num = num - 1;
自增和自减运算符的示例
#include <iostream>
using namespace std;
int main(){
int num1 = 240;
int num2 = 40;
num1++; num2--;
cout<<"num1++ is: "<<num1<<endl;
cout<<"num2-- is: "<<num2;
return 0;
}
输出:
num1++ is: 241
num2-- is: 39
4)逻辑运算符
逻辑运算符与二进制变量一起使用。它们主要用于条件语句和循环以评估条件。
C++中的逻辑运算符是:&& || !
假设我们有两个布尔变量b1
和b2
。
如果b1
和b2
都为真,则b1 && b2
将返回true
,否则它将返回false
。
如果b1
和b2
都为假,则b1 || b2
将返回false
,否则返回true
。
!b1
将返回与b1
相反的东西,这意味着如果b1
为假则为真,如果b1
为真则返回false
。
逻辑运算符的示例
#include <iostream>
using namespace std;
int main(){
bool b1 = true;
bool b2 = false;
cout<<"b1 && b2: "<<(b1&&b2)<<endl;
cout<<"b1 || b2: "<<(b1||b2)<<endl;
cout<<"!(b1 && b2): "<<!(b1&&b2);
return 0;
}
输出:
b1 && b2: 0
b1 || b2: 1
!(b1 && b2): 1
5)关系运算符
我们在 C++中有六个关系运算符:== != > < >= <=
- 如果左侧和右侧都相等,则
==
返回true
- 如果左侧不等于右侧,则
!=
返回 true。 - 如果左侧大于右侧,
>
返回true
。 - 如果左侧小于右侧,
<
返回true
。 - 如果左侧大于或等于右侧,则
>=
返回true
。 - 如果左侧小于或等于右侧,则
<=
返回true
。
关系运算符的示例
#include <iostream>
using namespace std;
int main(){
int num1 = 240;
int num2 =40;
if (num1==num2) {
cout<<"num1 and num2 are equal"<<endl;
}
else{
cout<<"num1 and num2 are not equal"<<endl;
}
if( num1 != num2 ){
cout<<"num1 and num2 are not equal"<<endl;
}
else{
cout<<"num1 and num2 are equal"<<endl;
}
if( num1 > num2 ){
cout<<"num1 is greater than num2"<<endl;
}
else{
cout<<"num1 is not greater than num2"<<endl;
}
if( num1 >= num2 ){
cout<<"num1 is greater than or equal to num2"<<endl;
}
else{
cout<<"num1 is less than num2"<<endl;
}
if( num1 < num2 ){
cout<<"num1 is less than num2"<<endl;
}
else{
cout<<"num1 is not less than num2"<<endl;
}
if( num1 <= num2){
cout<<"num1 is less than or equal to num2"<<endl;
}
else{
cout<<"num1 is greater than num2"<<endl;
}
return 0;
}
输出:
num1 and num2 are not equal
num1 and num2 are not equal
num1 is greater than num2
num1 is greater than or equal to num2
num1 is not less than num2
num1 is greater than num2
6)按位运算符
有六个按位运算符:& | ^ ~ << >>
num1 = 11; /* equal to 00001011*/
num2 = 22; /* equal to 00010110 */
按位运算符执行逐位处理。
num1 & num2
比较num1
和num2
的相应位,如果两个位相等则生成 1,否则返回 0。在我们的例子中它将返回:2,这是00000010
,因为在num1
和num2
的二进制形式中,只有倒数第二位匹配。
num1 | num2
比较num1
和num2
的相应位,如果任一位为 1,则生成 1,否则返回 0。在我们的例子中,它将返回 31,即00011111
。
num1 ^ num2
比较num1
和num2
的相应位,如果它们不相等则生成 1,否则返回 0。在我们的例子中它将返回 29,相当于00011101
。
~num1
是一个补码运算符,只是将位从 0 更改为 1,1 更改为 0。在我们的示例中,它将返回 -12,相当于11110100
。
num1 << 2
是左移位运算符,它将位移到左边,丢弃最左边的位,并将最右边的位赋值为 0。在我们的例子中,输出为 44,相当于00101100
。
注意:在下面的示例中,我们在此移位运算符的右侧提供 2,这是位向左移动两个位置的原因。我们可以更改此数字,并且位将按照移位运算符右侧指定的位数移动。同样适用于右移位运算符。
num1 >> 2
是右移位运算符,它将位向右移动,丢弃最右位,并将最左边的位指定为 0。在我们的例子中,输出为 2,相当于00000010
按位运算符的示例
#include <iostream>
using namespace std;
int main(){
int num1 = 11; /* 11 = 00001011 */
int num2 = 22; /* 22 = 00010110 */
int result = 0;
result = num1 & num2;
cout<<"num1 & num2: "<<result<<endl;
result = num1 | num2;
cout<<"num1 | num2: "<<result<<endl;
result = num1 ^ num2;
cout<<"num1 ^ num2: "<<result<<endl;
result = ~num1;
cout<<"~num1: "<<result<<endl;
result = num1 << 2;
cout<<"num1 << 2: "<<result<<endl;
result = num1 >> 2;
cout<<"num1 >> 2: "<<result;
return 0;
}
输出:
num1 & num2: 2
num1 | num2: 31
num1 ^ num2: 29
~num1: -12
num1 << 2: 44 num1 >> 2: 2
7)三元运算符
此运算符计算布尔表达式并根据结果赋值。
语法:
variable num1 = (expression) ? value if true : value if false
如果表达式结果为true
,则将冒号(:
)之前的第一个值赋给变量num1
,否则将第二个值赋给num1
。
三元运算符的例子
#include <iostream>
using namespace std;
int main(){
int num1, num2; num1 = 99;
/* num1 is not equal to 10 that's why
* the second value after colon is assigned
* to the variable num2
*/
num2 = (num1 == 10) ? 100: 200;
cout<<"num2: "<<num2<<endl;
/* num1 is equal to 99 that's why
* the first value is assigned
* to the variable num2
*/
num2 = (num1 == 99) ? 100: 200;
cout<<"num2: "<<num2;
return 0;
}
输出:
num2: 200
num2: 100
杂项运算符
C++ 中很少有其他运算符,如逗号运算符和 sizeof
运算符。我们将在单独的教程中详细介绍它们。
C++ 中的运算符优先级
如果表达式具有多个运算符,则确定首先需要对哪个运算符求值。顶部的运算符具有较高优先级,底部具有较低优先级。
-
一元运算符
++ -- ! ~
-
乘法
* / %
-
加法
+ -
-
移位
<< >>
-
关系
< <= > >=
-
相等
== !=
-
位与
&
-
位异或
^
-
位或
|
-
逻辑与
&&
-
逻辑或
||
-
三元
?:
-
赋值
= += -= *= /= %= >>= <<= &= ^= |=
控制语句
C++ 中的if
语句
原文: https://beginnersbook.com/2017/08/cpp-if-else-statement/
有时我们只有在满足或不满足特定条件时才需要执行一个语句块。这被称为决策,因为我们在程序逻辑中做出决定后执行某个代码。对于 C++ 中的决策,我们有四种类型的控制语句(或控制结构),如下所示:
a)if
语句
b)嵌套if
语句
c)if-else
语句
d)if-else-if
语句
C++ 中的if
语句
if
语句包含条件,后跟语句或一组语句,如下所示:
if(condition){
Statement(s);
}
if
括号(通常称为正文)中的语句仅在给定条件为真时才执行。如果条件为假,则完全忽略正文中的语句。**
if
语句的流程图
if
语句的示例
#include <iostream>
using namespace std;
int main(){
int num=70;
if( num < 100 ){
/* This cout statement will only execute,
* if the above condition is true
*/
cout<<"number is less than 100";
}
if(num > 100){
/* This cout statement will only execute,
* if the above condition is true
*/
cout<<"number is greater than 100";
}
return 0;
}
输出:
number is less than 100
C++ 中的嵌套if
语句
当在另一个if
语句中有if
语句时,它被称为嵌套if
语句。嵌套的结构如下所示:
if(condition_1) {
Statement1(s);
if(condition_2) {
Statement2(s);
}
}
如果
condition_1
为true
,则执行Statement1
。只有条件(condition_1
和condition_2
)都为真时,Statement2
才会执行。
嵌套if
语句的示例
#include <iostream>
using namespace std;
int main(){
int num=90;
/* Nested if statement. An if statement
* inside another if body
*/
if( num < 100 ){
cout<<"number is less than 100"<<endl;
if(num > 50){
cout<<"number is greater than 50";
}
}
return 0;
}
输出:
number is less than 100
number is greater than 50
在 C++ 中使用if-else
语句
有时你有一个条件,如果条件为真,你想要执行一段代码,如果相同的条件为假,则执行另一段代码。这可以使用if-else
语句在 C++ 中实现。
这是if-else
语句的外观:
if(condition) {
Statement(s);
}
else {
Statement(s);
}
如果条件为真,则if
内的语句将执行,如果条件为假,则else
内的语句将执行。
if-else
的流程图
if-else
语句的示例
#include <iostream>
using namespace std;
int main(){
int num=66;
if( num < 50 ){
//This would run if above condition is true
cout<<"num is less than 50";
}
else {
//This would run if above condition is false
cout<<"num is greater than or equal 50";
}
return 0;
}
输出:
num is greater than or equal 50
C++ 中的if-else-if
语句
当我们需要检查多个条件时使用if-else-if
语句。在这个控制结构中,我们只有一个if
和一个else
,但是我们可以有多个else if
块。这是它的样子:
if(condition_1) {
/*if condition_1 is true execute this*/
statement(s);
}
else if(condition_2) {
/* execute this if condition_1 is not met and
* condition_2 is met
*/
statement(s);
}
else if(condition_3) {
/* execute this if condition_1 & condition_2 are
* not met and condition_3 is met
*/
statement(s);
}
.
.
.
else {
/* if none of the condition is true
* then these statements gets executed
*/
statement(s);
}
注意:这里要注意的最重要的一点是,在if-else-if
中,只要满足条件,就会执行相应的语句集,忽略其余。如果没有满足条件,则执行else
内的语句。
if-else-if
的示例
#include <iostream>
using namespace std;
int main(){
int num;
cout<<"Enter an integer number between 1 & 99999: ";
cin>>num;
if(num <100 && num>=1) {
cout<<"Its a two digit number";
}
else if(num <1000 && num>=100) {
cout<<"Its a three digit number";
}
else if(num <10000 && num>=1000) {
cout<<"Its a four digit number";
}
else if(num <100000 && num>=10000) {
cout<<"Its a five digit number";
}
else {
cout<<"number is not between 1 & 99999";
}
return 0;
}
输出:
Enter an integer number between 1 & 99999: 8976
Its a four digit number
C++ 中的switch-case
语句
当我们有多个条件并且我们需要根据条件执行不同的操作时,使用switch case
语句。当我们有多个条件时,我们需要在满足特定条件时执行一个语句块。在这种情况下,我们可以使用冗长的 if..else-if
语句或switch case
。冗长if..else-if
的问题是当我们有几个条件时它会变得复杂。switch-case
是处理这种情况的干净而有效的方法。
switch case
语句的语法:
switch (variable or an integer expression)
{
case constant:
//C++ code
;
case constant:
//C++ code
;
default:
//C++ code
;
}
即使break
语句是可选的,switch case
语句也大量使用break
语句。我们将首先看到一个没有break
语句的例子,然后我们将讨论switch case
和break
。
switch-case
示例
#include <iostream>
using namespace std;
int main(){
int num=5;
switch(num+2) {
case 1:
cout<<"Case1: Value is: "<<num<<endl;
case 2:
cout<<"Case2: Value is: "<<num<<endl;
case 3:
cout<<"Case3: Value is: "<<num<<endl;
default:
cout<<"Default: Value is: "<<num<<endl;
}
return 0;
}
输出:
Default: Value is: 5
说明:在swicth
中我给出了一个表达式,你也可以给出变量。我给了表达式num + 2
,其中num
值是 5,并且在相加之后表达式得到 7。由于没有用值 4 定义的情况,所以执行了默认情况。
switch-case
流程图
它求值表达式或变量的值(基于switch
括号内给出的内容),然后根据结果执行相应的情况。
switch-case
中的break
语句
在我们讨论break
语句之前,让我们看看当我们在switch case
中不使用break
语句时会发生什么。请参阅以下示例:
#include <iostream>
using namespace std;
int main(){
int i=2;
switch(i) {
case 1: cout<<"Case1 "<<endl;
case 2: cout<<"Case2 "<<endl;
case 3: cout<<"Case3 "<<endl;
case 4: cout<<"Case4 "<<endl;
default: cout<<"Default "<<endl;
}
return 0;
}
输出:
Case2
Case3
Case4
Default
在上面的程序中,我们在switch
括号内部有变量i
,这意味着无论变量i
的值是什么,都会执行相应的case
块。我们已将整数值 2 传递给switch
,因此控制流切换到case 2
,但是在case 2
之后我们没有使用break
语句,导致控制流继续到后续case
直到结束。然而,这不是我们想要的,我们想要执行正确case
块并忽略其余的块。这个问题的解决方案是在每个case
块之后使用break
语句。
当您希望程序流从switch
主体中出来时,使用break
语句。每当在switch
主体中遇到break
语句时,执行流程将直接从switch
中出来,忽略其余的情况。这就是您必须使用break
语句结束每个case
块的原因。
让我们采用相同的例子,但这次使用break
语句。
#include <iostream>
using namespace std;
int main(){
int i=2;
switch(i) {
case 1:
cout<<"Case1 "<<endl;
break;
case 2:
cout<<"Case2 "<<endl;
break;
case 3:
cout<<"Case3 "<<endl;
break;
case 4:
cout<<"Case4 "<<endl;
break;
default:
cout<<"Default "<<endl;
}
return 0;
}
输出:
Case2
现在您可以看到只有case 2
被执行,其余的后续case
被忽略了。
为什么我在default
块不使用break
语句?
控制流本身会在默认情况下从switch
中出来,所以我之后没有使用break
语句,但是如果你想要它可以使用它,那么这样做是没有害处的。
重要笔记
1)case
并不总是需要顺序1,2,3
等。它可以在case
关键字后面包含任何整数值。此外,case
不需要始终按升序排列,您可以根据要求以任何顺序指定它们。
2)您也可以在switch-case
中使用字符。例如:
#include <iostream>
using namespace std;
int main(){
char ch='b';
switch(ch) {
case 'd': cout<<"Case1 ";
break;
case 'b': cout<<"Case2 ";
break;
case 'x': cout<<"Case3 ";
break;
case 'y': cout<<"Case4 ";
break;
default: cout<<"Default ";
}
return 0;
}
3)允许嵌套switch
语句,这意味着你可以在另一个switch
内部使用switch
语句。但是应该避免使用嵌套的switch
语句,因为它会使程序更复杂,更不易读。