IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> Windows下使用VSCode搭建C++开发环境——仅通过配置xxx.json文件 -> 正文阅读

[开发工具]Windows下使用VSCode搭建C++开发环境——仅通过配置xxx.json文件

最近在尝试使用VSCode搭建C++开发环境,而目前听说过2种方式:

(1)一种就是网上常说的要分别对launch.json,c_cpp_properties.json,tasks.json这3个文件

(2)直接使用cmake的方式

但是无论是哪种方式,对于复杂的C++工程,尤其是涉及到要包含各种复杂的头文件时,经常会遇到“找不到头文件”而显示波浪号的问题。博主经过反复尝试,目前分别对使用cmake和不使用cmake两种构建工程的方式进行了尝试,终于成功,在此对其中的细节和关键点进行记录,方便自己后续可以复现。

目录

1.仅使用VSCode自带的各种json文件来进行配置


目标工程结构如下:

VSCodeWorkplace2

? ? ? ?|——.vscode

? ? ? ?|——MyClass

? ? ? ? ? ? ? ? |——include

? ? ? ? ? ? ? ? ? ? ? ? ?Parent.h

? ? ? ? ? ? ? ? ? ? ? ? ?Child.h

? ? ? ? ? ? ? ? ? ? ? ? ?Blob.h? ? ? ?

? ? ? ? ? ? ? ? Parent.cpp

? ? ? ? ? ? ? ? Child.cpp

? ? ? ?|——main.cpp

文件包含关系如下:

Parent.cpp包含Parent.h,Child.cpp包含Child.h,Blob.h直接实现一个完整的class

main.cpp包含Parent.h,Child.h,Blob.h

接下来从最简单的main.cpp逐步增加上述文件完成工程的构建

  • 首先创建一个基本的只包含main.cpp的工程

(1)新建工程:“打开文件夹”:

新建并选择这个文件夹:

然后就可以看到下面的了:一开始什么都没有

(2)接下来先新建main.cpp。

输入以下内容:

#include <iostream>
using namespace std;

int main(){
    cout << "Hello World!" << endl;
    return 0;
}

再创建launch.json:

??选择1(“运行和调试”),再“创建launch.json”,再选择“C++(GDB/LLDB)”(这里特别说明一下,一般只有安装了MinGW之后才会有这个,具体安装方法自行百度),再按照下面的选择:

?然后在下面的“终端”就可以看见下面运行成功:

?此时目录结构变成这样:

相当于VSCode已经为我们创建好了最基础的配置文件,而其中的main.exe就是生成的二进制可执行文件。

  • 接下来继续创建MyClass目录

(1)按照下图创建目录:

源码分别如下:

Parent.h

#ifndef PARENT_H
#define PARENT_H
class Parent
{
public:
    static int num; //设置静态成员变量
    static void get_value();
public:
    Parent();
    virtual ~Parent();
    virtual void print();
    
};

#endif

?Parent.cpp

#include "Parent.h"
#include <iostream>

Parent::Parent(){
    std::cout << "Create a parent" << std::endl;
}

Parent::~Parent(){
    std::cout << "Delete a parent" << std::endl;
}

void Parent::print(){
    std::cout << "I am Parent!" << std::endl;
}

void Parent::get_value(){
    std::cout << "Parent value is " << num << std::endl;
}

int Parent::num = 0;

Child.h

#ifndef CHILD_H
#define CHILD_H
#include "Parent.h"

class Child: public Parent{
public:
    Child();
    ~Child();
    void print();
};


#endif

Child.cpp

#include "Child.h"
#include <iostream>

Child::Child(){
    std::cout << "Create a child!" << std::endl;
}

Child::~Child(){
    std::cout << "Delete a Child" << std::endl;
}

void Child::print(){
    std::cout << "I am Child!" << std::endl;
}

?Blob.h

#ifndef BLOB_H
#define BLOB_H
#include <iostream>

class Blob{
public:
    Blob() : data_(nullptr), size_(0){
        log("Blob's default constructor");
    }

    explicit Blob(unsigned int size) : data_(new char[size]), size_(size){
        log("Blob's parameter constructor");
    }

    ~Blob(){
        log("Blob's destructor");
        delete[] data_;
    }

    //拷贝构造函数
    Blob(const Blob& other){
        log("Blob's copy constructor");
        data_ = new char[other.size_];
        memcpy(data_, other.data_, other.size_);
        size_ = other.size_;
    }

    //重载赋值操作符
    Blob& operator= (const Blob& other){
        log("Blob's copy assignment operator");
        if (this == &other){
            return *this;
        }
        delete[] data_;
        data_ = new char[other.size_];
        memcpy(data_, other.data_, other.size_);
        size_ = other.size_;
        return *this;
    }

    //移动构造函数
    Blob(Blob&& other) : data_(other.data_), size_(other.size_){
        log("Blob's move constructor");
        other.data_ = nullptr;
        other.size_ = 0;
    }

    //重载移动赋值操作符
    Blob& operator= (Blob&& other){
        data_ = other.data_;
        size_ = other.size_;
        other.data_ = nullptr;
        other.size_ = 0;
        return *this;
    }

private:
    char* data_;
    unsigned int size_;
    void log(const char* msg){
        std::cout << "[" << this << "]" << msg << std::endl;
    }
};

#endif

?此时在Parent.cpp和Child.cpp里面都会看到波浪号如下:

?(2)接下来就开始解决文件包含的问题

进入“命令面板”,开始配置C/C++:编译配置(JSON)

?在.vscode目录下可以看到生成了一个c_cpp_properties.json,其中需要特别改动的如下

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**"  //改动:这个是为了解决由于无法解析头文件包含的问题而显示出来的波浪号,当然,这个也与后续的编译有关
            ],
            "windowsSdkVersion": "10.0.17763.0",
            "compilerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\bin\\Hostx64\\x64\\cl.exe",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "windows-msvc-x64"
        }
    ],
    "version": 4
}

其中${workspaceFolder}是VSCode自定义的变量,表示当前工作路径,即F:\VSCodeWorkplace2。当然,还定义了其他的变量,参考网上其他帖子将可能会用到的变量贴出来:

${workspaceFolder} :表示当前workspace文件夹路径,也即/home/Coding/Test

${workspaceRootFolderName}:表示workspace的文件夹名,也即Test

${file}:文件自身的绝对路径,也即/home/Coding/Test/.vscode/tasks.json

${relativeFile}:文件在workspace中的路径,也即.vscode/tasks.json

${fileBasenameNoExtension}:当前文件的文件名,不带后缀,也即tasks

${fileBasename}:当前文件的文件名,tasks.json

${fileDirname}:文件所在的文件夹路径,也即/home/Coding/Test/.vscode

${fileExtname}:当前文件的后缀,也即.json

${lineNumber}:当前文件光标所在的行号

${env:PATH}:系统中的环境变量
————————————————
版权声明:本文为CSDN博主「扎不下村村长」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/weixin_39249524/article/details/105438814

再看tasks.json,改动如下

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe 生成活动文件",
            "command": "D:\\SoftWareInstall\\mingw64\\bin\\g++.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "${workspaceFolder}\\MyClass\\Parent.cpp",    //改动:增加Parent.cpp
                "${workspaceFolder}\\MyClass\\Child.cpp",     //改动:增加Child.cpp
                "-IF:\\VSCode_workplace\\MyClass\\include",   //改动:增加头文件路径
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "调试器生成的任务。"
        }
    ],
    "version": "2.0.0"
}

当然,当然为了简化,可以更改成下面这样:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe 生成活动文件",
            "command": "D:\\SoftWareInstall\\mingw64\\bin\\g++.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "${workspaceFolder}\\MyClass\\*.cpp",    //改动:此处采用通配符的形式
                //"${workspaceFolder}\\MyClass\\Parent.cpp",
                //"${workspaceFolder}\\MyClass\\Child.cpp",
                "-I",
                "F:\\VSCode_workplace\\MyClass\\include",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "调试器生成的任务。"
        }
    ],
    "version": "2.0.0"
}

另外,为了测试完整的工程,把main.cpp改成如下样子:

#include <iostream>
//#include "Blob.h"
#include "Parent.h"
#include "Child.h"

int main(int, char**) {
    std::cout << "Hello, world!\n";
    //Blob *blob = new Blob();
    //delete blob;
    //blob = nullptr;
    
    Child* child = new Child();
    Parent* parent = child;
    parent->print();
    delete parent;
    parent = nullptr;
}

至此,会发现还有波浪号问题(但是编译运行没问题)。通过查询,发现是clang的设置问题,按照如下设置,把Clang的Diagnostic的Enable的√去掉

?此处是有参考VScode编译C++,首次成功,多编译几次头文件显示not found的解决方法

至此,头文件的波浪号和无法找到头文件的问题就解决了。

(3)编译运行,选择“运行”中的“启动调试”或“以非调试模式运行”

?这里作者通过快速截图,将编译过程的命令展示如下:

运行结果如下:

至此,整个工程的编译运行都完成了,并且看不到任何波浪号。

(4)讨论:

  • ${file}表示当前正在打开的文件的绝对路径,特别注意,这个变量并不是固定。

比如,你当前正在打开的是main.cpp,你停留在main.cpp文件上,你去点击“以非调试模式运行(Ctrl + F5)”,那么其实VSCode就会根据你刚才在tasks.json中args来先进行编译。

从上面编译过程的截图可以看到-g后面有3个.cpp文件(-g是指为编译过程增加调试信息,具体可以百度),后两个可以理解,是我们自己增加的;

但是还有一个F:\VSCodeWorkplace2\main.cpp是怎么来的呢?只能是${file}转化来的,而前面说过,我们是停留在main.cpp页面上去执行“以非调试模式运行(Ctrl + F5)”,那么${file}就会转化为main.cpp这个文件的绝对路径。之前作者以为${file}是这个tasks.json的绝对路径,但是编译过程却根本没有显示,反而是main.cpp的绝对路径,所以其实就说明${file}是会变换的。

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-10-11 17:42:38  更:2021-10-11 17:44:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 0:20:19-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码