c++编程学习复习笔记(一 基础)

面向对象概述与C++输入输出
使用<iostream>时,由于C++的标准库中所有标识符都被定义于一个名为std的namespace中,因此其后必须带上语句“using namespace std;”.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
	float a = 23.4563243;
	cout << "a = " << a << endl;
	cout << "a = " << setprecision(4) << a << endl;  //输出整数 + 小数的有效位数a=23.45
	cout << "a =" << fixed << setprecision(4) << a << endl; //为了使精度设置的含义体现为小数位数。
	return 0;
}
#include <iostream>
using namespace std;
int main()
{
	char s[100];
	cin >> s;// 输入不带空格的字符串数据,如果带空格字符串,需要用到cin.get(s,100);
	cout << s << endl;
	return 0;
}
  • 面向过程的程序设计方法,以功能为中心,强调功能(过程)抽象。实现了操作的封装,但数据是公开的,数据与对数据的操作分离,数据缺乏保护。功能易变,程序维护困难。因为功能往往针对某个程序而设计,这使得程序功能难以复用。基于功能分解的解题方式与问题空间缺乏对应。图形用户界面很难用过程来描述和实现。
实参与形参的三种结合方式:值调用、传址调用和引用调用
  • 在形参名前加上引用说明符“&”即将其声明为引用,实参则直接采用一般的变量名。
  • 在函数调用时,形参就成了实参的别名,对引用的操作就等同于直接对主函数中原变量的操作。
值调用
#include <iostream>
using namespace std; 
void fun (int x, int y)
{
	int tmp = x;
	x   = y;
	y   = tmp;
}
int main()
{	int a = 1,b = 2;
	cout << "Before exchange:a= " << a << ",b= " << b << endl;
	fun(a, b);
	cout << "After  exchange:a= " << a << ",b= " << b << endl;
	return 0;
}

运行结果:
Before exchange:a=1,b=2
After  exchange:a=1,b=2
传址调用:
//传址调用是双向的地址传递,通过指针访问地址间接实现交换两个整形变量的值。

#include <iostream>
using namespace std; 
void fun (int *x, int *y)
{
	int tmp = *x;
	*x   = *y;
	*y   = tmp;
}
int main()
{	int a = 1,b = 2;
	cout << "Before exchange:a= " << a << ",b= " << b << endl;
	fun(&a, &b);
	cout << "After  exchange:a= " << a << ",b= " << b << endl;
	return 0;
}

运行结果:
Before exchange:a=1,b=2
After  exchange:a=2,b=1

引用调用
//通过引用(变量的别名)直接实现交换两个整形变量的值。
//效果与地址调用相同,但是比传址更方便、直接。

#include <iostream>
using namespace std; 
void fun (int &x, int &y)
{
	int tmp = x;
	x   = y;
	y   = tmp;
}
int main()
{	int a = 1,b = 2;
	cout << "Before exchange:a= " << a << ",b= " << b << endl;
	fun(a, b);
	cout << "After  exchange:a= " << a << ",b= " << b << endl;
	return 0;
}

运行结果:
Before exchange:a=1,b=2
After  exchange:a=2,b=1

从结构体到类

结构体
  • C语言的结构体是把相互有关联的数据元素组成一个单独的统一体,从这个角度来说,结构体实现了数据的封装。
  • 结构体成员的访问时公开的,即允许结构体外部访问结构体成员。
  • 三种访问方式
    • 结构体变量: 采用结构体变量名.成员的方式。
    • 结构体指针: 采用结构体指针名->成员的方式。
    • 结构体数组:采用结构体数组名[下标].成员的方式。
实例
#include <iostream>
using namespace std;
struct computer//计算器结构体
{
	int op1,op2;//两个操作数
	char ch;//运算符
};
int main()
{
 computer a;

 cin>>a.op1>>a.ch>>a.op2;

 switch(a.ch)   
 {   
   case '+':cout<<a.op1+a.op2<<endl;break;   
   case '-':cout<<a.op1-a.op2<<endl;break;   
   case '*':cout<<a.op1*a.op2<<endl;break;   
   case '/':if(a.op2==0)   
                 cout<<"不能被0除"<<endl;   
              else    
                  cout<<a.op1/a.op2<<endl;
              break;   
    default:cout<<"运算符有错"<<endl;   
    }   
 return 0;
}

结构体变量用法
computer a; // 定义结构体变量a, c++ 中省略struct
cin >> a.op1 >> a.ch >> a.op2; // 结构体成员访问方式:结构体变量名.成员
结构体指针用法
computer a, *p = &a;  //定义结构体变量a和结构体指针p,p指向 a
cin >> p->op1 >> p->ch >> p ->op2;  //结构体指针访问方式:结构体指针名->成员
结构体变量作函数参数(值调用)
void run(computer b)   //函数定义
run(a);       //函数调用
结构体变指针作函数参数(地址调用)
void run(computer *pb)

run(&a);   
结构体数组
computer a[100], *p=a;   //定义结构体数组a和指针p

for(i = 0; i < n; i++)
{
	cin >> p[i].op1 >> p[i].ch >> p[i].op2; //结构体数组指针访问方式:结构指针名[下标].成员
//还可以用(指针名+下标)->成员形式访问,例如:p[i].ch 等价于(p+i)->ch
}
动态数组
#include <iostream>
using namespace std;
int main()
{	
        int n,i;
        cin>>n;//输入数组大小
        int *p =new int[n];//根据n的值动态申请数组
	p[0]=1;
	p[1]=1;
	for(i=2; i<n; i++)
	    p[i]=p[i-2]+p[i-1];
	cout<<p[n-1]<<endl;
        delete []p;//释放数组空间
	return 0;
}

//C++中new申请空间时直接指定数据类型,因此不需要像C中malloc函数那样再做类型转换。

单链表
#include <iostream>
using namespace std;
struct computer//计算器结构体
{	int op1,op2;//两个操作数
	char ch;//运算符
	computer *next;//链表对一个指针域成员,指向下一个结点
};
int n;//链表结点个数 
computer *creat() //用creat函数创建链表
{ computer *head,*p1,*p2;
  n=0;//新建链表 
  p1=p2=new computer;//用new动态申请结点
  cin>>p1->op1>>p1->ch>>p1->op2; //输入一个结点数据 
   head=NULL;
   while(p1->op1!=0)//假设操作数1输入0表示结束 
   {  n=n+1;
	  if(n==1) head=p1;
	  else  p2->next=p1;
	  p2=p1;
	  p1=new computer; //申请一个结点 
	  cin>>p1->op1>>p1->ch>>p1->op2; //输入一个结点数据  
	}
   p2->next=NULL;    
   return(head);
}

void run(computer *p)  //计算处理
{
    if(p!=NULL)
    do
    { switch(p->ch)   
 		{   
   		case '+':cout<<p->op1<<"+"<<p->op2<<"="<<p->op1+p->op2<<endl;break;   
   		case '-':cout<<p->op1<<"-"<<p->op2<<"="<<p->op1-p->op2<<endl;break;   
   		case '*':cout<<p->op1<<"*"<<p->op2<<"="<<p->op1*p->op2<<endl;break;   
   		case '/':cout<<p->op1<<"/"<<p->op2; 
		        if(p->op2==0)   
                 cout<<"不能被0除"<<endl;   
              else    
                 cout<<"="<<p->op1/p->op2<<endl;
              break;   
	    default:cout<<p->op1<<p->ch<<p->op2<<"运算符有错"<<endl;   
    }   
    p=p->next;
    }while(p!=NULL);
}

int main()
{
   computer *pt,*p,*p1;
   pt=creat();//创建链表 
   run(pt);//计算链表的全部结点 
   //释放动态申请的结点。
    p=pt;
     while(p!=NULL)   
     {  p1=p->next;
        delete p;//动态申请的链表,需要用delete释放
        p=p1;             
    }    
    return 0;
}

  • 类是c++数据封装的基本单元,他把数据和函数封装在一起。
//说明部分 (类体)
class <类名>
{
	public :
		<公有段数据及成员函数>
	protected:
		<保护段数据及成员函数>
	private:
		<私有段数据及成员函数>
};

//实现部分
	<各成员函数的实现>
关键字public、private、protected 为访问权限控制符,规定成员的访问权限,出现顺序和次数限制;

	公有(public)成员提供了类的接口功能,不仅可以被成员函数访问,而且可以在类外被访问;
	私有(private)成员是被类隐藏的数据,只有该类的成员或友元函数才可以访问,通常将数据成员定义为私有成员。
	保护(protected)成员具有公有成员或私有成员的特性。

定义成员函数

成员函数的定义及实现在类中完成(内联函数)
为了提高运行时的效率,对于较简单的函数可声明为内联形式。
内联函数体中不要有复杂结构(如循环语句和switch语句)。
在类中声明内联成员函数的方式:
将函数体放在类的声明中。
使用inline关键字。

例2.7中:类外定义的成员函数GetAverage(),如果使用inline描述,则是内联函数。即GetAverage函数类外定义写成如下形式:
inline float CStuScore::GetAverage()
   {
      return (float)((fScore[0] + fScore[1] + fScore[2])/3.0);
   }

成员函数的定义及实现在类外完成
将类体和其成员函数分开定义,是开发大型程序通常采用的方法。
在类中加函数声明,在类体外定义成员函数时须按下述格式:
  函数类型  类名::成员函数名(参数表)
  {
	函数体
  }
其中,作用域运算符::是用来标识某个成员函数是属于哪个类的。
成员函数的定义及实现与类在不同的文件中完成
类定义的头文件和类的成员函数定义的文件

例如: student.h 文件中放 CStuScore类的声明,stud.cpp中放类外定义的成员函数。
引入对象

①访问一般对象的成员的语法格式:
对象名.数据成员名
对象名.成员函数名(参数表)
②访问指向对象的指针的成员的语法格式:
对象指针名 -> 数据成员名
对象指针名 -> 成员函数名(参数表)
③访问对象数组元素的成员的语法格式:
对象数组名[下标].数据成员名
对象数组名[下标].成员函数名(参数表)

对象的成员具有不同访问类型:main函数可以访问公有成员,不能访问私有成员。私有数据保密,main函数中(类外)通过公有函数调用来设置私有数据成员的值。

面向对象程序设计
  • 以数据为中心,强调数据抽象
  • 数据与操作合二为一,实现了数据的封装,加强了数据的保护(数据安全)
  • 对象相对稳定,有利于程序维护。因为对象往往具有通用性,使得程序容易重用。
  • 基于对象/类的解题方式与问题空间有很好的对应。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

+、-、#表示成员的可见性,分别对应public、private、protected


构造函数与对象初始化

  • 构造函数用于创建类对象,初始化其成员。
  • 析构函数用于撤销类对象。

对象的私有数据成员初始化

  • 若对象定义时若未显式初始化,与变量类似,全局对象和静态对象在定义时初值为0,局部对象在定义时初值为不确定的值。一旦建立一个对象,对象通常都需要有一个有意义的初值。
  1. 在类中定义一个具有初始化功能的成员函数。每当创建一个对象时,就调用这个成员函数,实现初始化。
  2. 建立对象的同时,自动调用构造函数,使用定义类对象时包含了对象分配存储空间和初始化的双重任务。
  • 由于类的唯一性和对象的多样性,因此C++规定构造函数与类同名。特点为
    • 构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。

    • 在对象创建时由系统自动调用。

    • 如果程序中未声明,则系统自动产生出一个缺省形式的构造函数。

    • 构造函数可以有参数,也可以重载。可以为内联函数、重载函数、带默认形参值的函数。

    • 构造函数无返回类型,但是不要加void。

    • C++ 规定,每一个类必须有一个构造函数,没有构造函数就不能创建任何对象。

    • 若未定义一个类的构造函数,则C++ 提供了一个缺省的构造函数,该缺省构造函数是一个无参数的构造函数,仅仅负责创建对象,而不做任何初始化工作;

    • 只要一个类定义了一个构造函数,C++ 就不再提供缺省的构造函数。如还需要无参数构造函数,则必须自己定义;

    • 与变量定义类似,在用缺省构造函数创建对象时,如果创建的是全局对象或静态对象,则对象成员数据全为0;局部对象创建时,其成员数据是无意义的随机数。

#include <iostream>
#include <iomanip>
using namespace std;

class computer        //计算器定义
{
    //数据默认权限为私有
    int op1;
    char ch;
    int op2;

public:
    computer(int a, char c, int b)
    {
        op1 = a;
        ch  = c;
        op2 = b;
    }
    void show();
};

void computer::show()
{
    switch(ch)
    {
        case '+':
            cout<<op1 + op2<<endl;
            break;
        case '-':
            cout<<op1 - op2<<endl;
            break;
        case '*':
            cout<<op1 * op2<<endl;
            break;
        case '/':
            cout<<op1 / op2<<endl;
            break;
        default:
            cout<<"运算符有错"<<endl;
    }
}

int main()
{
    computer a(3,'-',5);//定义对象并初始化
    a.show();//计算并输出结果
    return 0;
}
  • 注: 构造函数可采用以下两种方式将值赋给其成员。
  1. 如上例所示:
  2. 使用函数体前的初始值表,例如:

computer(int a, char b, int c):op1(a),ch(b),op2©{}

this 指针
  • 每个类的成员函数中都隐含了一个 this 指针,该指针指向正在调用成员函数的对象。如下所示:
computer(int op1,char ch,int op2) 
{
	this->op1=op1; 
	this->ch=ch;
	 this->op2=op2;
 } 

  • computer构造函数中:3个形参与数据成员同名,所以使用this指针进行区别。如果不同名,可以不用this指针进行区分。类的其他成员函数碰到形参与数据同名的情况,也用this指针进行同样的区分。

函数重载

一组参数和返回值不同的函数共用一个函数名。

  • 注: 重载函数之间必须在参数的类型或个数方面有所不同。只有返回值类型不同的几个函数不能重载。
int add(int x, int y);
形参类型不同
float add(float x, float y);
int add(int x, int y);
形参个数不同
int add(int x, int y, int z);

在这里插入图片描述

带默认形参值的函数

  • 函数定义时,可在形参列表中预先给一些默认值
  • 当调用这种函数时,若为想应参数给出实参,则用实参初始化对应形参;如果没给出,则自动采用预先给定的默认形参值。
    注意:
    要保证所有的缺省参数均放在参数表的最后,即默认参数值必须按从右向左的顺序声明。如:
    void func(int x, int n1 = 1, int n2 = 2);

在这里插入图片描述


默认形参值与函数的调用位置
  • 调用出现在函数体实现之前时,缺省形参值必须在函数原形中给出;当调用出现在函数体实现之后时,缺省形参值需在函数实现时给出。

在这里插入图片描述


参考:https://blog.csdn.net/PattyAndSmith/article/details/84330773

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值