一般会将 C++ 划分为所谓的中级语言,从底层的 C 语言发展而来,提供了比 C 更丰富的特性,而又没有提供类似 Java、Python 等语言的高级特性,所以,介于中间,称之为中级语言。
随着 C++11 标准的发布,以及更新的 C++0x 标准,C++ 提供的功能越来越完善。
这里仅简单介绍下基本的概念。
简介
C++ 是由 Bjarne Stroustrup 于 1979 年在贝尔实验室开始设计开发的,进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言,可以行于多种平台上,如 Windows、MAC、Unix、Linxu 等各种版本。
不过不像 Java、Python 这类语言,其运行依赖于底层的虚拟机进行解释,编译后的代码无需重新编译,而 C++ 在不同的平台上需要重新编译,以生成不同的二进制文件。
这里,主要以 Linux 平台上的 gcc 为例。
示例
如下是一个最简单的 Hello World 示例。
#include <iostream>
using namespace std;
int main(void)
{
cout << "Hello World" << endl;
return 0;
}
通过 using namespace std
标示使用标准的命名空间,可以选择使用多个,只要不发生命名空间的冲突即可。在编译的时候这里使用最新的 C++11 标准,可以使用 g++ -std=c++11 -o hello hello.cpp
命令进行编译。
面向对象
在面向对象的编程 (OOP) 中包含了比较重要的三大特性:封装、继承和多态。
封装
使代码模块化,通过对象封装了其特性和行为,分别称之为成员变量以及成员函数。其中成员访问管理分成了三类:
- public 类、类对象、派生类、派生类对象 均可访问。
- protected 类、派生类可以访问;类对象、派生类对象不可以访问。
- private 只有类内部可以访问。
继承
扩展已经存在的代码,可以通过已有的数据类型定义新的类型,继承老成员,并定义新成员。
包括了公有 Public、保护 Protected、私有 Private 继承,共三种方式,主要是对其父类成员中的访问权限设置。
多态 Polymorphisn
C++ 支持编译时以及运行时的多态性,分别通过函数重载以及虚函数来实现,注意,运行时的多态是通过虚拟函数指针实现的,也就是为什么是运行时动态绑定。
可以查看如下的 double GetArea(Shape &s)
函数,其入参是基类 Shape
,允许用户传入其派生类对象,例如 Rectangle
、Circle
,也就是调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。
示例
如下是一个简单的示例,展示一些基础的特性,其中 class Shape
包含了纯虚函数,也就是一个接口类,无法进行实例化,而派生类包含了四边形、圆形的实现。
#include <iostream>
using namespace std;
// Abstract Base Class
class Shape {
protected:
private:
// int pri{}; // init, equal to int pri=0
public:
// Pure Virtual Function
virtual double Area() = 0;
};
class Rectangle : public Shape {
//protected:
private:
double width, height;
public:
// Simple Constructor
Rectangle(double w, double h) {
width = w;
height = h;
}
// Destructor
~Rectangle() = default; // equal to ~Rectangle() { } Do nothing
double Area() override {
return width * height;
}
};
class Circle : public Shape {
private:
static constexpr double PI = 3.1415926;
double radius;
public:
explicit Circle(double r) {
radius = r;
}
double Area() override;
[[nodiscard]] double GetDiameter() const;
friend void DumpInfo(Circle &c);
};
void DumpInfo(Circle &c) {
cout << "radius is " << c.radius << endl;
}
double Circle::Area() {
return PI * radius * radius;
}
double Circle::GetDiameter() const {
return radius * 2;
}
double GetArea(Shape &s) {
return s.Area();
}
int main() {
Rectangle rec(10, 100);
Circle c(10);
DumpInfo(c); // friend function
cout << "Area Rect=" << GetArea(rec) << " Circle=" << GetArea(c) << "Diameter=" << c.GetDiameter() << endl;
}
类中函数的。
其它
初始化列表
对于简单的对象可以使用初始化列表,但是需要注意,初始化列表是按照声明的顺序,而非在初始化列表中的顺序。
#include <iostream>
class Rectangle {
public:
double width, height;
Rectangle(double w): height(w), width(height) {}
};
int main() {
Rectangle r(1.2);
std::cout << r.height << std::endl << r.width << std::endl;
}
上述的代码初始化时,实际上会先将 width
初始化为 height
,而此时的 height
变量没有初始化,是个随机值,通常会很大;接着,才会通过入参 w
初始化 height
变量。所以,最终的结果导致 width
变量值随机,height
的值是入参。
另外,在初始化列表中可以使用 new
关键字,例如 Array(int s): size(s), data(new int[s])
。
多线程
C++11 提供了标准的线程库 std::thread
,可以不再显式依赖 pthread 提供的线程库,实际上底层仍然使用的是该库,这也就是为什么链接时需要添加 -lpthread
或者 -pthread
选项。
#include <thread>
#include <unistd.h>
#include <iostream>
using namespace std;
void hello(void)
{
usleep(1000);
cout << "Hello Concurrent World" << endl;
cout << "Current thread ID " << this_thread::get_id() << endl;
}
int main(void)
{
thread thd(hello);
cout << "Hello World" << endl;
thd.join();
cout << "All threads joined!" << endl;
return 0;
}
友元
可以是一个函数或者类,这样通过友元函数可以直接访问类中的 private
以及 protected
的成员,需要注意,友元不是类的成员,也就不能使用 this
指针。