1. 项目介绍
案例:士兵突击
需求:
(1) 士兵 许三多 有一把枪,叫做 AK47 (2) 士兵 可以 开火 (3) 士兵 可以 给枪装填子弹 (4) 枪 能够 发射 子弹 (5) 枪 能够 装填子弹 —增加子弹数量
开发:
- 开发
枪类 - 开发
士兵类
2. 合理设置项目目录
2.1 新建文件夹
- 新建
Include 文件夹存放.h头文件 - 新建
src 文件夹存放.cpp 源文件
3 创建类
3.1 创建Gun类
创建Gun.h 和 Gun.cpp
#pragma once
#include <string>
using namespace std;
class Gun
{
public:
Gun(string type);
void addBullet(int bullet_num);
bool shoot();
private:
int _bullet_count;
string _type;
};
编写Gun.cpp 源代码,实现Gun类的接口
#include "Gun.h"
#include <iostream>
using namespace std;
Gun::Gun(string type){
this -> _bullet_cout=0;
this ->_type=type;
}
void Gun::addBullet(int bullet_num)
{
this->_bullet_count += bullet_num;
}
bool Gun::shoot()
{
if (this -> _bullet_count <=)
{
cout <<"There is no bullet" <<endl;
return false;
}
this -> _bullet_count -=1;
cout << "shoot successfully!"<<endl;
return true;
}
3.2 创建士兵类Soldier
创建Soldier.h 和 Soldier.cpp
- 编写Soldier.h头文件,定义Soldier类的接口
#pragma once
#include <string>
#include "Gun.h"
using namespace std;
class Soldier
{
public:
Soldier(string name);
~Soldier();
void addBullerToGun(int num);
void addGun(Gun *ptr_gun);
bool fire();
private:
string _name;
Gun* _ptr_gun;
};
- 编写
Soldier.cpp 源代码,实现Soldier类的接口
#include "Soldier.h"
using namespace std;
Soldier::Soldier(string name)
{
this -> _name = name;
this -> _ptr_gun = nullptr;
]
void Soldier :: addGun(Gun *ptr_gun)
{
this ->_ptr_gun = ptr_gun;
}
void Soldier ::addBulletToGun(int num)
{
this -> _ptr_gun ->addBullet(num);
}
bool Soldier::fire()
{
this ->_ptr_gun ->shoot();
}
Soldier::~Soldier()
{
if (this -> _ptr_gun == nullptr)
{
return ;
}
delete this -> _ptr_gun;
this -> _ptr_gun = nullptr;
}
3.3 创建main函数
新建main.cpp文件,并编写代码
#include "Gun.h"
#include "Soldier.h"
void test()
{
Soldier sanduo("xusanduo");
sanduo.addGun(new Gun("AK47"));
sanduo.addBullerToGun(20);
sanduo.fire();
}
int main()
{
test();
return 0;
}
完整的代码结构如下:
4. 编译
4.1 g++方式编译
g++ main.cpp src/Soldier.cpp src/Gun.cpp -Iinclude -o myg++exe
./myg++exe
shoot successfully!
编译可增加其他可选项如-Wall (显示警告信息), -g (调试格式) ,-O2 (对代码进行优化)
g++ main.cpp src/Soldier.cpp src/Gun.cpp -Iinclude -o myg++exe -Wall -g -O2
4.2 cmake方式编译
4.2.1 编写CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(SOLDIERFIRE)
include_directories(${CMAKE_SOURCE_DIR}/include)
add_executable(my_camke_exe main.cpp src/Gun.cpp src/Soldier.cpp)
如果需要增加一些编译选项如:-O2,-d ,-Wall,-std11++等,可以在project命令后增加一行命令:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 -Wall")
4.2.2 编译
mkdir build
cd build
cmake ..
编译成功,生成了makefile文件,然后执行make命令,生成可执行文件
make
可以通过编写build.sh 来完成编译过程,build.sh 的内容如下:
if [ ! -d build ] ; then
mkdir build
fi
cd build
cmake ..
make -j4
执行bash就可以完成编译,该方式编译可减少重复工作
bash build.sh
4.2.3 运行可执行文件
./my_cmake_exe
结果:shoot successfully!
注:当修改了代码,可以执行make进行重新编译 重新编译
make
cmake的方式重新编译只会对修改的文件,重新编译,这对于大型的项目,是非常节约时间的
5. 调试
(1) 点击vscode调试按钮,点击create a launch.json file ,因为在调试之前需要配置lanuch.json 和 task.json 文件
(2) 选择 C++(GDB/LLDB),然后在选择 g++ 生成和调试活动文件` (3) 弹出launch.json文件
其中program 和 preLaunchTask 命令是两条非常重要的命令,后续需要更改这两条命令。 (4) 修改lanuch.json 文件,这里先只修改lanuch.json文件,调试看看
由于之前生成了cmake 版和g++ 版可执行文件,可执行文件的位置如下所示:
先调试build文件下cmake 编译的my_cmake_exe 文件,修改program 为目标可执行文件的绝对路径
"program":"${workspaceFolder}/build/my_cmake_exe",
其中preLaunchTask 先暂时不修改,进行注释掉,修改后的launch.json 文件如下
{
"version": "0.2.0",
"configurations":[
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request":"launch",
"program":"${workspaceFolder}/build/my_cmake_exe",
"args":[],
"stopAtEntry":false,
"MIMode":"gdb",
"setupCommands":[
{
"description":"为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures":true
}
],
"miDebuggerPath":"/usr/bin/gdb"
}
]
}
(4) 重新编译
cd build
make
(5) 设置断点,并在Vscode中按F5 进行调试 注:在调试过程中,debug 进入不了代码内部,可能是CMakeLists.txt中的编译选项的问题,如下:
set(CMAKE_CXX_FLAGS "{CMAKE_CXX_FLAGS} -g -O2 -Wall")
选项发生了冲突,-O2 会对代码进行优化,-g 需要输出带调试信息,因此需要修改CMakeLists.txt ,去掉-g -O2 ,添加set(CMAKE_BUILD_TYPE Debug)
cmake_minimum_required(VERSION 3.0)
project(SOLDIERFIRE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_BUILD_TYPE Debug)
include_directories(${CMAKE_SOURCE_DIR}/include)
add_executable(my_camke_exe main.cpp src/Gun.cpp src/Soldier.cpp)
重新make一下,就可以调试了
(6) 修改tasks.json 文件 点击 VScode工具栏中的Terminal ->Configure Task ,重新修改tasks.json 文件,修改好的tasks.json 文件如下:
{
"version": "2.0.0",
"options":{
"cwd": "${workspaceFolder}/build"
},
"tasks":[
{
"type":"shell",
"label":"cmake",
"command":"cmake",
"args":[
".."
]
},
{
"label":"make",
"group":{
"kind":"build",
"isDefault":true
},
"command":"make",
"args":[
]
},
{
"label":"Build",
"dependsOrder":"sequence",
"dependsOn":[
"cmake",
"make"
]
}
]
}
此时可将launch.json 中的 preLaunchTask 改为
"preLaunchTask":"Build"
完整的launch.json 如下:
{
"version": "0.2.0",
"configurations":[
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request":"launch",
"program":"${workspaceFolder}/build/my_cmake_exe",
"args":[],
"stopAtEntry":false,
"MIMode":"gdb",
"setupCommands":[
{
"description":"为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures":true
}
],
"preLaunchTask":"Build",
"miDebuggerPath":"/usr/bin/gdb"
}
]
}
(7) 完成launch.json 和tasks.json 后,即可实现自动化调试功能,不需要手动编译可执行文件 测试 在main.cpp中添加一行代码,如下:
#include "Gun.h"
#include "Soldier.h"
#include <iostream>
using namespace std;
void test()
{
Soldier sanduo("xusanduo");
sanduo.addGun(new Gun("AK47"))
sanduo.addBulletToGun(20);
sanduo.fire();
}
int main(int argc,char **argv)
{
cout << "This is a test string ..." <<endl;
test();
return 0;
}
增加一行新代码后不需要手动编译可执行文件,可直接进行调试,系统通过preLaunchTask 自动帮忙编译
参考
B站UP主:xiaobing1016
|