一、从C到C++

        读前须知:本文主要针对有过一定C语言基础的同学,默认大家已经熟悉C语言的基础语法,指针,结构体等特性,在此基础上学习C++;因此将关注C++的新特性,较为基础的知识将不再赘述。

1、C++对C的增强

        针对大规模软件开发问题,C++编程语言被开发出来。C++兼容C,并在以下两方面对C语言进行扩充

  1. 在面向过程机制基础上,对C语言进行功能扩展;
  2. 增加了面向对象的机制。

2、最简单的C++程序结构

        在C语言中可以通过函数,主函数,结构体的方式编写程序;在C++中仍然适用;大部分语法完全一致;对于作用域标识符{}的限制不再要求严格,但在一些条件控制,嵌套循环中还是需要严格使用{}标识作用域;下面来看一个最简单的C++程序,它包含了一些常见的操作。

#include <iostream>//<>包含系统库,""包含自定义库
#define pi 3.145159//宏 c语言中实现
const float PI = 3.1415926515;//c艹中使用const定义常变量
//使用const分配了内存空间 define则不会
using namespace std;//命名空间cin cout 定义在这个库内
//或者 std:: cout
int main()
{	
	int a = 1;
	float b = 2;
	cout << a;//C++中的输出
	cout << b;
	cout << a << b;
	int x,y;
	cin >> x >> y;//C++中的输入
	
	cout << x << y << endl;//endl:换行
    return 0;
}

  以此段程序为例说明一些基础知识。

2.1程序注释

        

//注释,给人看的,C++中这样注释
//"//"后跟注释即可
//当然,C++兼容C,也可使用C风格的/*qwqwq*/来注释,但谁不想省事呢

 2.2预处理命令

        以之前的程序为例

#include <iostream>//<>包含系统库,""包含自定义库
#define pi 3.145159//宏 c语言中实现

        以#开头的指令,在预编译阶段执行,做代码文本替换工作,包括 库包含 和 宏定义

2.2.1库包含

#include <iostream>//<>包含系统库,""包含自定义库

        #include 也可以将另一个.cpp文件导入,在编译时直接把那个.cpp文件粘贴到这个位置上。通常把类定义、成员函数的编写、主函数分成三个文件写,就是通过这种方式。(有种import的感觉但又不完全是) 

2.2.2宏定义

#define 标识符 替换文本

2.3命名空间

        注意到这句话

using namespace std;

        命名空间的设计是为了解决可能的不同源文件重名,变成可执行文件时出错的问题

        这里的std就是C++中所有标准库的命名空间。std中也包含者之后会提到的输入与输出cin、cout,因此在使用这两个函数时也需要加上命名空间:

std::cin>>q;
std::cout<<q;

        但这样写会很麻烦,在整个程序中频繁的使用会增大无聊的coding,因此可以用using namespace std;来说明使用了std这个命名空间,之后直接使用cin、cout即可。

2.4输入和输出

        在C中我们使用printf(),scanf()等函数进行输入输出,由于要记住一大堆的格式化字符串来输出,让人很头大;C++中为我们提供了更加简单的手段,那就是cin 和 cout

int main()
{	
	int a = 1;
	float b = 2;
	cout << a;//C++中的输出
	cout << b;
	cout << a << b;
	int x,y;
	cin >> x >> y;//C++中的输入
	
	cout << x << y << endl;//endl:换行
    cout << "hello world";
    return 0;
}

        可以看到,无论什么类型的数据,只需 cout<<data 即可自动识别并输出。还要注意的是 >> 和 >> 这两个新的操作符。并且十分易于阅读、组装输出内容。具体使用大家自行操作一下很快就能明白。

        注意到 endl ,这个特殊的保留字段是C++的换行标识符,当使用cout<<endl时,会让输出结果换行。区别C中的\n。

        当然兼容C,printf()和scanf()仍然适用。 

3、类

        在C中允许用户使用struct结构体来自定义数据类型,当然C++中也能使用,且在数据结构方面的程序中大量使用。C++中提供了类似的自定义功能,那就是类。

        类的功能远不止自定义数据类型,它是C从面向过程编程到C++面向对象编程的重要标志,在之后会详细讲解。

struct student
{
    int num;
    float score;
};//结构体

class student
{
    private://以下数据、函数是私有的(但一般就只让数据是私有的,
            //外部不能直接访问,需要用public中的接口函数进行访问)
        int num;
        float score;//数据成员
    public://以下数据、函数是公开的,外部可以直接访问,
           //通常在此编写接口函数对对象的数据成员进行修改
        void setdata()//成员函数
        {
            cin>>num;
            cin>>score;
        };
        void show()//接口函数,打印这个对象的数据成员
        {
            cout<<"num = "<<num<<endl;
            cout<<"score = "<<score<<endl;
        };
}//类

        这里简单对类和对象进行说明,有个大致的印象:在源文件中定义类,通过实例化获得对象。类相当于描述了一个事物应该具有什么属性,能干什么;对象则是具体到一个实例上,拥有这个实例的详细参数,可以进行操作达成目的。


class student
{
    private://以下数据、函数是私有的(但一般就只让数据是私有的,
            //外部不能直接访问,需要用public中的接口函数进行访问)
        int num;
        float score;//数据成员
    public://以下数据、函数是公开的,外部可以直接访问,
           //通常在此编写接口函数对对象的数据成员进行修改
        void setdata()//成员函数
        {
            cin>>num;
            cin>>score;
        };
        void show()//接口函数,打印这个对象的数据成员
        {
            cout<<"num = "<<num<<endl;
            cout<<"score = "<<score<<endl;
        };
}//类
int main()
{
    student stu1,stu2;//实例化出两个对象
    stu1.setdata();
    stu1.show();
    stu2.setdata();//让stu2这个对象干(执行函数)setdata这个事情
    stu2.show();
    return 0;

}

4、内置(内联)函数

        在C++中,提供了内置函数这一新特性。使用inline关键字来标识函数,使之成为内置函数。在程序执行时,当遇到一般的函数调用,数据流将跳转到函数体,执行相应的函数操作,再将返回值带回(或者不用返回),接着执行下面环节。但这样势必造成所需时间的增加。内联函数的出现允许一些短而频繁使用的函数在编译时直接将操作写在调用位置,无需跳转,加快了程序运行的速度。任何函数都可通过增加inline关键字变成内置函数,但推荐将短而频繁使用的函数变成内置,不然源文件可就太丑了...例如:

#include <iostream>//<>包含系统库,""包含自定义库
#define pi 3.145159//宏 c语言中实现
const float PI = 3.1415926515;//c艹中使用const定义常变量
//使用const分配了内存空间 define则不会
using namespace std;//命名空间cin cout 定义在这个库内
//或者 std:: cout
void functionsay();
inline int min(int a ,int b)//内置函数,小而频繁的,可直接声明加定义,inline关键字
{
	if (b>a)
	a = b;
	return a;
}
int Max(int x,int y);
int main()
{	
	int a = 1;
	float b = 2;
	cout << a;
	cout << b;
	cout << a << b;
	int x,y;
	cin >> x >> y;
	int out = Max(x,y);
	cout << out;
}

int Max(int x,int y)
{	
	int out ;
	if(x > y)
	{
		out = x;
	}
	else
	{
		out = x;
	}
	return out;
}

        同时,在类内进行函数体的编写编译器会自动把这个函数当作内置函数处理;在类外定义的函数则被当成普通函数。 当然在也可以在类内函数使用inline关键字进行强行标识,如

class A
{
    private:
        int a;
    public:
        A(){a = 1;};
        void sum();//没有加关键字,但在类内编写函数体,也会作为inline函数
        {
            a++;
        };
        inline void sum1();
        void sum2();

};
void A::sum1()//类内的声明和外部定义只需出现一个inline关键字即可强制转化为内置函数,也可以两个都加
{a+=2;};
int main()
{
    A a;
    a.sum;
    
}

5、函数的重载

        这个特性很重要,这个特性很重要,这个函数很重要。

        说三边,体现重要性蛤...函数的重载允许C++中两个不同的函数使用相同的名称,然后根据形参的不同、返回值类型的不同来自动识别究竟该调用哪个函数。最简单的,对于比较两个类型的最大值Max(),在int和double两个不同的类型调用时就可以不必编写两个不同名称的函数,简化了思维。

        同时,对于类内的一些函数,如构造函数,操作符等也都能进行重载,之后会详细说明。

        根据参数,返回类型来区别到底是哪个重载,也决定了C++在声明函数时,必须是完整的声明,不能像C中那样不给参数声明。

#include <iostream>//<>包含系统库,""包含自定义库
#define pi 3.145159//宏 c语言中实现
const float PI = 3.1415926515;//c艹中使用const定义常变量
//使用const分配了内存空间 define则不会
using namespace std;//命名空间cin cout 定义在这个库内
//或者 std:: cout
void functionsay();
inline int min(int a ,int b)//内置函数,小而频繁的,可直接声明加定义,inline关键字
{
	if (b>a)
	a = b;
	return a;
}
double Max(double x ,double y);

int Max(int x,int y);
int Max();
int main()
{	
	int a = 1;
	float b = 2;
	cout << a;
	cout << b;
	cout << a << b;
	int x,y;
	cin >> x >> y;
	int out = Max(x,y);
	cout << out;
}
int Max()
{
	cout<<"没有参数哦~~"<<endl;
};
int Max(int x,int y)
{	
	int out ;
	if(x > y)
	{
		out = x;
	}
	else
	{
		out = x;
	}
	return out;
}
double Max(double x, double y)
{
	double out ;
	if(x > y)
	{
		out = x;
	}
	else
	{
		out = x;
	}
	return out;
};

6、变量的引用

        先思考一个问题:当我们把实参传给一个函数的形参时,在函数里的操作针对的是实参还是形参?相信大家都知道,是形参。就比如交换两个变量的值这个函数,在C语言中我们是通过指针实现的。

void cswap(int *a,int *b)
{   //用指针的形式实现
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

        只有通过这样 ,才能使得两个内存中的数据进行交换

         如果不使用指针,直接把实参传递到形参,则把实参的数据拷贝到形参所代表的内存空间里,在操作后原本的实参没有变化。因此需要传递指针,对内存空间上的数据进行修改。

        但是类似的指针操作过于繁琐,也不利于程序的可读性。因此C++提供了一个新的特性:变量的引用。

        先来看下怎么引用

int aliass()
{
    int a;
    int &b = a;
    //初始化引用 类型需要保持一致 共享同一内存单元

    int c;
    int &d =a;//引用
    int *p = &a;//指针
    
}

        这个没有任何意义的函数里演示了如何建立引用。就是通过

类型 & 引用变量明 = 要被引用的变量 

        这个引用相当于是变量的别名,对于引用的修改会直接作用到变量的内存空间,相当于两个变量共享同一内存空间。没有为引用分配内存空间,它只是别名,这也是引用和指针的重要区别。

        那么对于上面的swap函数就可以写成这样 

void swap(int &a,int &b)
{   //引用实例 可以不必使用指针
    int temp;
    temp = a;
    a = b;
    b = temp;
}

        代码瞬间简单多了 

        需要注意的是不能建立引用数组,也不能建立void类型的引用。后者好理解 ,void不能建立数据类型。

int &arr[3] = {1,2,3};//错误,&arr[3]代表建立了引用数组,但由于不能给引用分配内存空间,
                      //因此无法将后面的数据保存;同时数组建立后也没有自己的名字,无法编译通过
int arr[3] = {1,2,3};//正确,建立一个名为arr,三个数据的数组
int (&b)[3] = arr//正确,这是建立数组的引用

        这里(&b)[3]的含义就是强行把&和名称b结合在一起,意思就是引用啦。 

        

7、动态内存分配

        编程中我们往往需要对内存进行动态分配,这也是C++和C贴近底层的体现。

        在C中动态内存分配机制使用了malloc和free两个函数.

#define SIZE 100
int* arr = (int*)malloc(SIZE * sizeof(int));
free(arr);

        C++中也提供了这样的内存分配机制:new和delete。这两个函数务必搭配使用

double* pf1 = NULL;
try
    {
        pf1 = new double;//使用new分配
        *pf1 = 90;
        cout<<*pf1<<endl;
    }
    catch(bad_alloc err)
    {
        cout<<err.what()<<endl;
    };
delete pf1;

        使用new在自由储存区动态分配一块内存区域,delete用于释放new运算符开辟的内存空间。若自由储存区被耗尽,将无法成功分配内存,若不处理将会抛出bad_alloc,可用catch捕获该异常。详细使用见番外篇:new和delete

8、const关键词

        const是constant的缩写,意为不变的,恒定的。在C++中存在const保留关键词,它可以声明一个常量,编译器在编译时直接将其锁死,不可对其的值进行修改,只能读取。在初始化一个数据,对象时,使用const关键词,将其变为常对象。用const修饰的变量值在程序任意位置不能再被修改,就像一个常数一样使用。不可对其值进行修改,赋值,只能读取。

int a = 12;
const int a1 = 114514;
int const a2 = 114514;
a1 = 1919810;//错误,a1已被cosnt修饰,成为常量
a2 = 13;//cosnt在数据类型声明前后均可
a = 11;//普通变量的修饰
const int i;//错误,必须进行初始赋值
string s = "qwqwq";
string const s1 = "qaqaq";
const string s2 = "wqwqwq";
s = "123";//正确
s1 = "qqqqq";//错误
s2 = "swdadw";//错误

更详细的用法见番外篇:还在填坑呜呜呜 

9、作用域操作符::

        在c++中规定每个变量或函数都有自己的有效作用域。只能在变量或函数的作用域内使用该变量或函数

        作用域是一种操作符,使用::表示。其左操作数是scope作用域范围,右操作数是scope内定义的实体名

#include <iostream>
float a = 12.3;
int main()
{
    int a = 5;
    std::cout<<a<<std::endl;
    std::cout<<::a<<std::endl;
    return 0;
}

10、C++程序的编写与实现

        

 8、总结

        以上是C++与C的一些基础知识,可以帮助大家快速从C过度到C++,但这只是冰山一角。在接下来的blog中将重点讲解C++的特性。

猜你喜欢

转载自blog.csdn.net/Gelercat/article/details/127163431