原创 [源码+PDF文档]重学C++ ,重构你的C++知识体系

2024-3-3 10:50 152 2 2 分类: 物联网


从学习角度看,C++是一门“见效慢”的语言;学习曲线陡峭,语言本身复杂。但,如果你想了解很多编程语言的思想源泉,想要一窥大型企业级开发工程的思路,想开发别人做不了的高性能程序,那C++就是你的好伙伴。


一、什么是C++?

    C++是一种面向对象的计算机程序设计语言,作为C语言的继承,C++不仅能进行C语言的过程化程序设计,而且可进行以抽象数据类型为特点的基于对象的程序设计,还能进行基于过程的程序设计。C++是一种静态数据类型检查的、支持多重编程范式的通用程序设计语言。它的设计风格支持数据抽象、面向对象程序设计、过程化程序设计、泛型程序设计等。


二、C++工作原理

 C++语言的程序因为要体现高性能,所以都是编译型的。但其开发环境,为了方便测试,将调试环境做成解释型的。即开发过程中,以解释型的逐条语句执行方式来进行调试,以编译型的脱离开发环境而启动运行的方式来生成程序最终的执行代码。

  生成程序是指将源码(C++语句)转换成一个可以运行的应用程序的过程。如果程序的编写是正确的,那么通常只需按一个功能键,即可搞定这个过程。该过程实际上分成两个步骤。

  第一步是对程序进行编译,这需要用到编译器。编译器将C++语句转换成机器码;如果这个步骤成功,下一步就是对程序进行链接,这需要用到链接器。链接器将编译获得机器码与C++库中的代码进行合并。C++库包含了执行某些常见任务的函数(“函数”是子程序的另一种称呼)。例如,一个C++库中包含标准的平方根函数sqrt,所以不必亲自计算平方根。C++库中还包含一些子程序,它们把数据发送到显示器,并知道如何读写硬盘上的数据文件。


三、C++有什么用?

1、游戏开发

C++在游戏开发中具有广泛的应用,它可以满足游戏运行速度和计算能力的需求,并且可以提供强大的底层控制能力,例如使用C++开发游戏引擎如Unity和Unreal Engine。此外,C++在游戏服务器后端岗位中也有需求,包括游戏开发工程师等。掌握C++基础和数据结构,并了解开源引擎的实现,如使用开源引擎如Uniy和UE4,将有助于提升游戏开发效率。


2、嵌入式系统

嵌入式系统是C++的一种应用,包括照相机、汽车、火箭、电话交换机等等。嵌入式系统需要高效的执行速度和底层控制能力,而C++的高性能和指针机制可以满足这些需求。


3、 图形图像处理

图形图像处理是C++的一个重要应用方向,它主要涉及图像的获取、增强和复原、图像压缩、图像分割、彩色图像处理。图像表示等方面。


4、开发游戏和操作系统的能力

C++是一种非常常用的编程语言,尤其适合开发游戏和操作系统的能力。它可以帮助开发者开发高性能的游戏和操作系统,并且可以更好地理解这些系统的工作原理。


还有很多,就不一一举例。


四、就业情况

C++作为一种编程语言,在就业市场上一直保持着稳定的需求和较高的薪资水平。以下是C++就业的几个主要方向:


嵌入式开发——这是C++的一个重要应用领域,涉及硬件产品的驱动开发。许多知名企业如华为、小米、vivo等都在招聘C++嵌入式开发工程师,且薪资水平相对较高。

客户端开发——主要指开发Windows操作系统的桌面软件,如WPS、压缩软件等。技术栈通常包括C++和QT,这个领域的工作经验被认为是非常宝贵的,尤其是在金融、医疗等需要高效、稳定系统的领域。

游戏开发——C++在游戏开发领域非常受欢迎,因为它是许多游戏引擎和框架的基础。腾讯、网易、米哈游等游戏公司都在招聘C++游戏开发工程师,这个领域的薪资通常非常丰厚。

音视频处理——随着直播和短视频平台的兴起,音视频处理成为了一个热门领域。C++在这个领域有着广泛的应用,主要技术栈包括FFmpeg、WebRTC等。

服务端开发——C++在后端开发中占有一席之地,尤其是在需要高性能、极致压榨CPU的场景下。百度、腾讯等大型互联网公司都在使用C++进行服务端开发。

人工智能和机器学习——C++在这些领域也发挥着重要作用,尤其是在需要高效、稳定软件的情况下。


总的来说,C++在多个行业中都有广泛的应用,并且提供了多样化的职业发展路径。对于希望在技术领域发展的学生或专业人士来说,掌握C++技能是一个非常值得考虑的选择


五、代码实战

通过多态性建立通用游戏棋盘

在没有模板的情况下,构建通用游戏棋盘的最佳方法是使用多态性来存储通用的 GamePiece 对象。然后,你可以让每个游戏的棋子从 GamePiece 类继承。例如,在国际象棋游戏中,ChessPiece 将是 GamePiece 的派生类。通过多态性,编写为存储 GamePiece 的 GameBoard 也可以存储 ChessPiece。因为可能需要复制 GameBoard,所以 GameBoard 需要能够复制 GamePiece。这种实现使用多态性,所以一种解决方案是在 GamePiece 基类中添加一个纯虚拟的 clone() 方法,派生类必须实现它以返回具体 GamePiece 的副本。


这是基本的 GamePiece 接口:

class ChessPiece : public GamePiece {

public:

    std::unique_ptr clone() const override {

        // 调用复制构造函数来复制这个实例

        return std::make_unique(*this);

    }

};


GameBoard 的实现使用向量的向量和 unique_ptr 来存储 GamePieces:

GameBoard::GameBoard(size_t width, size_t height) : m_width { width }, m_height { height } {

    m_cells.resize(m_width);

    for (auto& column : m_cells) {

        column.resize(m_height);

    }

}


GameBoard::GameBoard(const GameBoard& src) : GameBoard { src.m_width, src.m_height } {

    // The ctor-initializer of this constructor delegates first to the

    // non-copy constructor to allocate the proper amount of memory.

    // The next step is to copy the data.

    for (size_t i { 0 }; i < m_width; i++) {

        for (size_t j { 0 }; j < m_height; j++) {

            if (src.m_cells[j]) {

                m_cells[j] = src.m_cells[j]->clone();

            }

        }

    }

}


void GameBoard::verifyCoordinate(size_t x, size_t y) const {

    if (x >= m_width) {

        throw out_of_range { format("{} must be less than {}.", x, m_width) };

    }

    if (y >= m_height) {

        throw out_of_range { format("{} must be less than {}.", y, m_height) };

    }

}


void GameBoard::swap(GameBoard& other) noexcept {

    std::swap(m_width, other.m_width);

    std::swap(m_height, other.m_height);

    std::swap(m_cells, other.m_cells);

}


void swap(GameBoard& first, GameBoard& second) noexcept {

    first.swap(second);

}


GameBoard& GameBoard::operator=(const GameBoard& rhs) {

    // Copy-and-swap idiom

    GameBoard temp { rhs }; // Do all the work in a temporary instance.

    swap(temp); // Commit the work with only non-throwing operations.

    return *this;

}


const unique_ptr& GameBoard::at(size_t x, size_t y) const {

    verifyCoordinate(x, y);

    return m_cells[x][y];

}


unique_ptr& GameBoard::at(size_t x, size_t y) {

    return const_cast&>(as_const(*this).at(x, y));

}

在这个实现中,at() 返回指定位置的棋子的引用,而不是棋子的副本。GameBoard 作为二维数组的抽象,应该通过给出索引处的实际对象而不是对象的副本来提供数组访问语义。

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
2
1
2
3
4
5
6
7
8
9
0
关闭 站长推荐上一条 /3 下一条