之前的C语言学习系列中,我们仔细讲解了C语言的一些基础知识。之后又写了21天C语言代码训练营系列,大家反馈很有收获。
从今天起,我们开始学习C++编程。C++的知识点并不比C语言少,如果从零开始讲解有些困难。幸好我的理念一直是通过具体的项目教大家学习编程。让我们跟着项目走,相信你一定能够迅速掌握最实用的C++技巧。
希望大家在初步学习C++之后再来学习这个系列,一定会让你爱上C++编程。
C++的价值
在这里我们用最简单的方式阐述一下究竟为什么C++比C语言高级。从功能的角度讲,用C++写的程序C语言也能够实现。那么C++究竟高级在哪儿呢?它就高级在引入了更加人性化的编程方式。
人们常说C是面向过程的语言,而C++在此基础上引入了面向对象和泛型两种全新的编程方式。而这两种新的编程方式更加接近我们现实中解决问题的思想,因此C++更好用一些。
编程语言高下之争一直是业内一个主要争论话题,多年以来从未停止。随着各种新语言的诞生,参加争论的派系也越来越多。
其实,我们大可不必纠结于语言,所有的语言都是为程序员服务的,解决现实中的问题才是我们最终的目的。所以,语言没有高下之分,只不过是使用语言的人参差不齐而已。
在我们学习C++时,千万不要把它和C语言分割开来,我们要把C++想象成为C语言的一个扩展,所有C语言的东西在这里都能继续使用。
创建C++项目
我们用Visual Studio来创建一个标准的控制台程序工程。创建过程请参考。与C语言项目的唯一区别是新建文件时要以cpp为后缀名。
第一段C++代码
我们在新创建的main.cpp文件中加入下面这段C++代码:
// main.cpp
#include <iostream>
using namespace std;
int main()
{
string str = "Hello World!";
cout << str.c_str() << endl;
return 0;
}
这是一个最基本的标准的C++源代码,在屏幕上打印“Hello World!”语句。大体上看和C语言的区别不大。我们来看看几个细节上的不同。
1. 头文件
C++的标准输入输出库不再是stdio.h,而是iostream。需要注意的是这里用的是<>而不是“”。原因我们在C语言教程中讲过了。值得注意的是,C++的标准库引用不需要加后缀名。
2. 命名空间
using namespace std;
这句话看着比较陌生。
C++中引入了命名空间的概念,std就是一个常用的命名空间。有了这行代码,后面的string和cout关键字才能正确被引用。如果没有这句话,我们在使用是需要这样写。
std::string str = "Hello World!";
std::cout << str.c_str() << std::endl;
“::”这个符号叫做域运算符,能够帮助我们引用某个命名空间下的任意关键字。
3. string类
C++一个非常大的进步是拥有了string类(字符串类),它能帮助我们处理最常用的字符串数据类型。
在《21天C语言代码训练营》中,我们通过C语言自己实现了一个string类型来管理字符串,如今这个工作C++标准库已经帮我们做好了。
4. 标准输入输出
在C++中,我们用cout和cin进行标准输入输出。它们代替了printf和scanf。具体的用法我们会在使用中慢慢了解。
Visual Studio代码调试
下面我们来运行一下前面这段代码。
1. 快捷键F6
这个快捷键的作用是编译项目中的全部代码。如果要看看有没有语法错误,就直接按这个键。
PS:如果在安装过程中,VS发现这个快捷键有冲突,也许会自动调整成别的键。在BUILD菜单中能够查看到这个快捷键。
2. 快捷键F5
调试运行代码。如果源代码没有编译,它会先进行编译之后运行。执行过程中,遇到断点会停下来。
3. 快捷键F9
增加或删除断点,方便调试。不要问我什么是断点,在C语言学习中你就该知道的。
4. 快捷键F10,F11
这两个快捷键负责单步调试,就是按一下执行一句话。前者遇到函数调用一次执行完,后者遇到函数调用会进入函数内部单步执行。
在调试代码时,这两个键非常有用。
5. 快捷键Ctrl + F5
忽略断点执行。就是不在断点处停下直接执行结束。
现在,我们在VS中使用“Ctrl+F5”运行我们刚才的代码。看到了下面的窗口。
实现第一个C++类
在《21天C语言代码训练营》中,很多人都说我们自己实现的string功能非常好用。下面是之前的头文件:
#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED
#define BUF_SIZE 100
typedef struct _tagString
{
char buf[BUF_SIZE];
int len;
}String;
void StringInit(String* pStr);
void StringSet(String* pStr, char* pBuf);
char* StringGetBuffer(String* pStr);
void StringAppend(String* pStr, char* pBuf);
#endif // STRING_H_INCLUDED
今天,我们用C++的类来封装这一组功能。功能的实现也不用之前的代码了,我们用C++自己的string来完成。
1. 头文件
新建String.h文件,加入下面代码。
#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED
#include <iostream>
using namespace std;
class String
{
public:
String(){}
~String(){}
void Init(char* pStr);
void Init(String str);
const char* GetBuffer();
void Append(char* pBuf);
private:
string m_str;
};
#endif // STRING_H_INCLUDED
这个头文件中,全部的功能代码都变成了String类的成员函数,这样,我们就可以用每一个String类的对象管理一个相应的字符串了。
这里需要注意,成员函数的函数名不再需要加上类名作为前缀了。也就是说不用再出现SringInit,StringAppend这样的函数名称了。
2. 源码文件
接下来我们实现String类的成员函数。创建String.cpp文件,代码如下:
#include "String.h"
void String::Init(char* pStr)
{
m_str = pStr;
}
void String::Init(String str)
{
m_str = (char*)str.GetBuffer();
}
const char* String::GetBuffer()
{
return m_str.c_str();
}
void String::Append(char* pBuf)
{
m_str.append(pBuf);
}
字符串实际上是保存在String的私有成员变量m_str中的,因此所有的功能其实是调用std::string给我们提供的API。
接下来我们写一段程序来测试一下我们的第一个C++类。在main.cpp中加入下面代码。
#include <iostream>
#include "String.h"
int main()
{
char a[] = "ABCDE";
char b[] = "FGHIJ";
String str;
str.Init(a);
cout << str.GetBuffer() << endl;
str.Append(b);
cout << str.GetBuffer() << endl;
String str1;
str1.Init(str);
cout << str1.GetBuffer() << endl;
return 0;
}
按Ctrl + F5看看结果吧。
其实,我们自己实现这个String类从功能角度来说意义不大,因为C++已经为我们提供了功能更强大的string类,但通过这段代码,我们能够清楚地看到在引入了类之后,C++的代码能够得到更好的封装,这对我们后面开发C++程序至关重要。
我是天花板,让我们一起在软件开发中自我迭代。
如有任何问题,欢迎与我联系。