精华内容
下载资源
问答
  • 创建一个类的时候,可能包含很多成员变量及成员函数,每个成员函数代码量可能非常大,这样就希望将成员函数 的实现放到独立的新的.cpp文件,形成一个.h文件类声明,多个.cpp文件类成员函数实现。实现方法如下: //...

    环境说明:

                QT版本5.12.0,QT Creater版本4.8.0X64,WIN10 64位,编译、调试器VS2015 amd64

    创建一个类的时候,可能包含很多成员变量及成员函数,每个成员函数代码量可能非常大,这样就希望将成员函数 的实现放到独立的新的.cpp文件,形成一个.h文件类声明,多个.cpp文件类成员函数实现。实现方法如下:

    //A.h
    class A
    {
    public:
        A();
        ~A();
    
    public:
        int a,b,c;
    
    public:
        //成员函数1
        void fun1();
        //成员函数2
        void fun1();
        //成员函数3
        void fun1();
            
          ...
    };
    
    //1.cpp
    #include "A.h"
    void A::func1()
    {
        //do somting
    }
    
    //2.cpp
    #include "A.h"
    void A::func2()
    {
        //do somting
    }
    
    //3.cpp
    #include "A.h"
    void A::func3()
    {
        //do somting
    }

    注意,经过试验验证(好吧,其实是把我折磨了几个小时,一点点排除发现的,网上也没见相关说明),分离出来的.cpp文件不要超过5个。

    如果超过5个,就会报链接错误,无法构建。爆出的错误如下:

                              cl.exe中的内部编译器错误

                              cl: 命令行 error D8000

    个人理解应该是和编译器有关,有兴趣的可以查查。

    展开全文
  • 1、出现的问题:”error LNK1169: 找到一个或多个多重定义的符号“的错误 ...有多个cpp文件和与之对应h文件,在main中调用这些文件时候需要包含进去,cpp文件中有包含h文件,main函数中也有h文件,当h文件中有定

    作者:liaojiacai    邮箱: ljc_v2x_adas@foxmail.com

    1、出现的问题:”error   LNK1169:   找到一个或多个多重定义的符号“的错误

    2、该问题出现的场景:(假设有一个A.h,A.cpp,main,在main中调用了A.cpp文件中的函数,A.cpp文件中的部分变量是在A.h文件中声明的)

    有多个cpp文件和与之对应的h文件,在main中调用这些文件时候需要包含进去,cpp文件中有包含h文件,main函数中也有h文件,当h文件中有定义的共有类时会出现这个问题,就是编译的时候出现重定义,之所以出现这个问题,是因为凡是包含h头文件的地方,都会执行一遍h文件里面的内容,cpp文件和main中都包含h文件,都会编译,这样谁先编译,那么等到编译另外一个文件的时候,h文件里面的东西都有了,再编译就会检查出重定义了,但是不包含h文件,那么h文件对应的cpp文件中的函数不能直接在main中使用,必须加extern,cpp文件不包含h文件,那么h文件中的部分变量没办法在cpp文件中定义

    3、解决方法:

    重定义主要是头文件重复包含反复编译了

    最直接的解决方法就是:

    以head.h文件为例,head.h文件在head.cpp和main.cpp头文件中都包含了这样重复编译就会出错,解决方法如下: 

    在有包含用到head.h的文件中最前面添加

    #if !define(HEAD_H)
            #define HEAD_H

    其实就是C++编程的基础知识,当然对没有系统学习过C++的,肯定是一脸懵逼!!!

    智慧的网友给出了很多的解决方法,也放在下面:

    方法1、参见博客

    http://www.cnblogs.com/A-Song/archive/2012/03/23/2413782.html

    这是基本的解决方法,就是把h文件中只放cpp文件中函数的声明,h中定义的变量都放在cpp文件的开头,cpp文件中不用包含h头文件,main中包含h头文件就OK了!!!

    方法2、可以在VS里面设置强制编译

    忽略这个问题这个方法也可行但是感觉很别扭,隐隐约约感觉到有问题,即使出了结果,感觉总有点不舒服,这种方法就是默认这里找到的同名的函数是一个,即两次编译的h文件是一个,忽略后面编译的一次

    方法3、(其实不是方法,这是c++的标准规范的调用)

    上面的两种办法的根本是没有搞清楚编译的过程,说白了就是没有搞清楚h文件,cpp文件,main文件之间的相互依赖关系,方法1会出现这样的问题,当我在h文件中声明的函数的参数中有在cpp文件中定义的类的时候,这种方法无解,因为方法1讲cpp文件需要的定义都放在cpp文件开始部分,h文件中声明的函数的参数又有cpp文件中定义的类,这样等等话,h文件中对函数申明失败,找不到使用了在cpp文件中定义的参数。如果在cpp文件和h文件中都声明了同一个类,这样h文件中声明带有这个类的参数的函数时候不会出现问题,但是h文件和cpp文件中都定义了同一个类,这明显重定义了。

    正确的使用方法是:

    下面举例子

    1)main里面:

    #include"Feature_Triangulate_3D_rebuild3.h"

    2)Feature_Triangulate_3D_rebuild3.cpp里面:

    #include"Feature_Triangulate_3D_rebuild3.h"

    3)Feature_Triangulate_3D_rebuild3.h里面

    #include"common.h"

    bool TestTriangulation(const vector<CloudPoint>& pcloud, const Matx34d& P, vector<uchar>& status);

    4)common.h里面

    struct CloudPoint {
    cv::Point3d pt;
    std::vector<int> imgpt_for_img;
    double reprojection_error;
    };

    std::vector<cv::Point3d> CloudPointsToPoints(const std::vector<CloudPoint> cpts);

    5)common.cpp里面

    #include"common.h"

    std::vector<cv::Point3d> CloudPointsToPoints(const std::vector<CloudPoint> cpts)
    {
    std::vector<cv::Point3d> out;
    for (unsigned int i = 0; i<cpts.size(); i++)
    {
    out.push_back(cpts[i].pt);
    }
    return out;
    }

    对上面说明main里面使用了Feature_Triangulate_3D_rebuild3.cpp文件中的TestTriangulation函数,TestTriangulation函数一个参数const vector<CloudPoint>& pcloud是自己定义的类,放在common.h里面,TestTriangulation函数里面调用了一个函数CloudPointsToPoints(const std::vector<CloudPoint> cpts),这个函数放在common.cpp文件中

    编译说明:

    从main开始,遇到#include"Feature_Triangulate_3D_rebuild3.h“时进入include"Feature_Triangulate_3D_rebuild3.h中,又遇到#include"common.h",把common.h里面的CloudPoint类申明了,把CloudPointsToPoints函数也申明了(申明的时候就是告诉到common.cpp里面去找这个CloudPointsToPoints这个函数),common.h里面编译完,回到nclude"Feature_Triangulate_3D_rebuild3.h中,执行#include"common.h"后面的bool TestTriangulation(const vector<CloudPoint>& pcloud, const Matx34d& P, vector<uchar>& status)函数申明,这个函数会遇到 有参数CloudPoint类和CloudPointsToPoints函数,这两个都在前面申明了,所以编译不会出现问题。所以mian函数里面的#include"Feature_Triangulate_3D_rebuild3.h"执行完毕,就把我们使用TestTriangulation函数要用到的东西全都搞定了。所有的cpp文件都通过h头文件调用编译成功。



    展开全文
  • .c .cpp .h

    2011-07-15 15:30:20
    基础: 一个.cpp对应一个obj,一个.obj就是一个编译单元,多个编译单元在链接的时候通过链接器链接,组成一个exe,就是一个程序。如果一个cpp需要另外一个cpp定义的函数,只需要在这个cpp中写上这个函数的声明就可以...
     
    

    基础:

      一个.cpp对应一个obj,一个.obj就是一个编译单元,多个编译单元在链接的时候通过链接器链接,组成一个exe,就是一个程序。如果一个cpp需要另外一个cpp定义的函数,只需要在这个cpp中写上这个函数的声明就可以了,注意在链接的过程中如果有同名的函数或者变量在不同的obj中,程序运行会报错。(实际上在编译的时候,就会提示出现重定义的错误。)在实际的调试过程中发现,变量的重定义在编译的过程中能够立即检测出来,而函数的重定义则不同,如果你首先在一个cpp里面实现该函数的定义,然后运行成功,然后在另外一个cpp函数里面再实现相同的函数的定义,那么程序将不会报错,rebuild all以后,报错,个人认为是编译器优化的原因。

     

    避免这种问题的方法:extern 和 static; extern是外部链接的意思,也就是除了这个单元,外部的单元

    也是能够访问这个函数的.static 是内部链接,自属于自己单元.

     

    心得:对于全局变量尽量不要在.h文件中定义,如果有两个.cpp及以上包含该.h文件,就会出现变量重定义。

             如果要使用全局函数,可以在一个cpp文件中定义该变量,在其他需要的.cpp文件中extern该函数即可             (不需要包含任何头文件)(.h文件在编译的时候会在cpp文件中扩建开)。

          对于static关键字,只能在当前编译单元看到,对外部不可见。

     

    记住: 在c++中,变量声明只有在受用extern关键字的时候才成立,其他情况都是定义,而在使用extern的同时给变量赋初值,那么声明变为定义,同时extern被编译器忽略(经过自己验证)。c++变量缺省情况下是全局的,对所有源文件是可见的,如果加上static关键字,会被认为是局部的变量,对外部不可见。

     

    1 不要把定义放在.h中,容易导致重复定义

    2 尽量把变量定义为static,限制在局部范围内,除非使用全局的。

    对于const和typedef是例外,const和typedef默认是局部的,不需要使用static,因此可以在.h文件中使用const变量不会产生重定义,编译器会为每一个引用该.h的源文件申请一份该变量的局部定义,就像该变量定义在该原文件中,但此时和其他使用该变量的源文件是独立的,彼此没有联系。

    3 对于static关键字,如果修饰函数内定义的变量或者类内部定义的成员变量时,称为静态变量,修饰其他变量时,称为局部变量。

     

    而对于函数,默认情况为extern, 一般函数都为“外部”函数, 

    所以在声明函数时不用加"extern". 

    如果在一个文件中声明函数时加了"static", 表示这个函数只在这个文件内可见。 

     

    <>h文件作用 
    1 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明, 
    2 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h) 

    <>h文件里应该有什么 
    常量,结构,类型定义,函数,变量申明 

    <>h文件不应该有什么 
    变量定义, 函数定义 

    <>extern问题 
    对于变量需要extern, 
    对于函数不需要因为函数的缺省状态是extern的.如果一个函数要改变为只在文件内可见,加static 

    <>include包含问题 
    虽然申明和类型定义可以重复,不过推荐使用条件编译#ifndef _FILENAME_H, #define _FILENAME_H, #endif 

    <>应该在那儿包含h文件 
    在需要的地方.比如某个提供接口的h文件仅仅被1.c文件需要,那么就在1.c文件里包含 

    条件编译目的是防止头文件的重复包含和编译,可能会导致编译速度降低,但不是错误!? 

    展开全文
  • jni中多个cpp类的使用

    2019-07-15 15:19:35
    主要完成的功能是使用生成jni对应的Test.h,新建Test.cpp写入内容,再去生成libTest.so,然后在Java类中加载

    测试环境描述

    以下内容所使用环境ubuntu、jdk1.8

    本文文件描述

    Test.java

    主要完成的功能是使用生成jni对应的Test.h,新建Test.cpp写入内容,再去生成libTest.so,然后在Java类中加载

    fingerprintExtract.cpp

    c++的一些功能类,为了方便在Test.cpp中被使用,把该文件编译成对应的.so库

    fftw

    在fingerprintExtract.cpp被使用,一个开源库,.configure、make的时候会生成.so库

    jni的描述

    JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植

    编译在后面使用到的fftw库

    ./configure --prefix=/home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output --enable-shared
    make -j32
    make install
    

    在这里插入图片描述
    修改库的搜索路径,或者把libfftw3.so.3拷贝到/usr/local/lib中,并重命名为libfftw3.so

    修改库路径的两种方法

    第一种方法,修改库路径

    sudo vim /etc/ld.so.conf
    

    在最后一行插入

    /home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output/lib
    

    编辑完成之后使用

    sudo ldconfig
    

    更新一下

    第二种方法,拷贝到/usr/local/lib

    sudo cp libfftw3.so.3 /usr/local/lib/libfftw3.so
    

    生成Java调用的入口点

    写对应的Java文件Test.java

    public class Test
    {
        static
        {
            System.load("/home/zy/test/zengraoli_jni_plus/libTest.so"); //libmain.so是jni要生成的so文件
        }
        public native void extractFingerPrint(String inputVoices, String  dataHash); // 声明jni导出的函数 //声明的add()函数,在后面他封装了类Twono中的Add()函数
        public static void  main(String[] args)
        {
            String inputVoices = "/home/zy/migudata/source/";
            String dataHash = "/home/zy/fingerPrint/fingerprint/data/hash709.txt";
            Test main = new Test();
            main.extractFingerPrint(inputVoices,dataHash); // 调用jni导出的函数extractFingerPrint
        }
    }
    

    用Java文件生成jni对应头文件Test.h

    javac Test.java
    javah Test
    

    补充Test.cpp文件

    写入以下内容

    #include "stdio.h"
    #include "Test.h"
    
    #include <fstream>
    #include <string>
    #include <time.h>
    #include "fingerprintExtract.h"
    
    
    using namespace std;
    
    JNIEXPORT void JNICALL Java_Test_extractFingerPrint
      (JNIEnv *env, jobject obj, jstring inputVoices, jstring dataHash)
    {
    printf("zengraoli begin.\r\n");
    
    const char *input = env->GetStringUTFChars(inputVoices, NULL);
            string inputPath = input;
            env->ReleaseStringUTFChars(inputVoices, input);
    
            const char *data = env->GetStringUTFChars(dataHash, NULL);
            string dataPath = data;
            env->ReleaseStringUTFChars(dataHash, data);
    
            fingerprintExtract fingerprintTemp;
            fingerprintTemp.fingerprintVoices(inputPath , dataPath);
    
    printf("zengraoli end.\r\n");
    
    }
    

    fingerprintExtract.h的内容如下

    #pragma once
    #include "hash.h"
    #include "fingerprint.h"
    #include "FileChange.h"
    #include "time.h"
    #include <dirent.h>
    //#include <Windows.h>
    //#include <io.h>
    class fingerprintExtract {
    private:
    public:
        void fingerprintVoices(string inputVoices, string dataHash);
        void ProcessVoices(const char *voicesPath);
    };
    

    fingerprintExtract.cpp主要涉及到一些业务操作,依赖fftw这个库,所以代码可以任意

    在linux上面编译生成fingerprintExtract.so

    fingerprintExtract.cpp在生成的.so的时候,依赖了hash、fingerprint、FileChange,这几个文件需要在生成时候一块编译

    g++ -fPIC -shared  -o libfingerprintExtract.so FileChange.cpp wav.cpp hash.cpp fingerprint.cpp fingerprintExtract.cpp
    

    ldd -r libfingerprintExtract.so
    

    查看一下.so,发现这个时候是没有引入fftw.a造成函数找不到的问题
    在这里插入图片描述
    但其他的函数都正确了

    那么只需要在生成Test.so的时候把这个.a库链接进来即可

    生成jni对应的so文件

    g++ -fPIC -I/home/wfx/usr/java/jdk1.8.0_111/include -I/home/wfx/usr/java/jdk1.8.0_111/include/linux -I/home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output/include -L/home/zy/test/zengraoli_jni_plus/fftw-3.3.8/output/lib -L. -shared -o libTest.so -lfftw3 -lfingerprintExtract Test.cpp
    

    查看libTest是否有函数找不到链接

    ldd -r libTest.so
    

    在这里插入图片描述

    执行Java文件中的main查看对应的函数是否被调用

    可以看到,调用已经没有问题了
    在这里插入图片描述

    判断.so文件是否为debug版本

    readelf -S libTest.so
    

    如果没有看到有debug字段,那么则直接就是release对应的.so文件

    展开全文
  • 有时候我们要一次运行多个文件,这时候我们可以使用Makefile!!! ◊make是什么?  make是一个命令工具,是一个解释makefile中指令的命令工具。它可以简化编译过程里面所下达的指令,当执行 make 时,make 会...
  • 如果你不想让你的源代码变得很难阅读的话,就请使用多个编译单元吧.(一个函数不能放到两个编译单元里面,但两个以上就可以分别放在一个单元,也就是cpp里面)那么就是一个.cpp对应一个.obj,然后将所有的obj链接起来(通过...
  • .h和.cpp文件的区别

    2017-03-07 16:22:12
    首先,我们可以将所有东西都放在一个.cpp文件内. 然后编译器就将这个.cpp编译成.obj,obj是什么东西? 就是编译单元了.... 也可以有多个编译单元组成....就请使用多个编译单元吧.(一个函数不能放... 那么就是一个.cpp对应一个
  • 如果你不想让你的源代码变得很难阅读的话, 就请使用多个编译单元吧.(一个函数不能放到两个编译单元里面,但两个以上 就可以分别放在一个单元,也就是cpp里面) 那么就是一个.cpp对应一个.obj,然后将所有的obj链接起来...
  • C++ .h .cpp(转)

    2013-08-24 13:16:18
    一个.cpp对应一个obj,一个.obj就是一个编译单元,多个编译单元在链接的时候通过链接器链接,组成一个exe,就是一个程序。如果一个cpp需要另外一个cpp定义的函数,只需要在这个cpp中写上这个函数的声明就可以了,注意...
  • .h和.cpp文件的区别 .

    2013-04-25 15:32:00
    首先,我们可以将所有东西都放在一个.cpp文件内. 然后编译器就将这个.cpp编译成.obj,obj是什么东西? 就是编译单元了.... 也可以有多个编译单元组成....就请使用多个编译单元吧.(一个函数不能... 那么就是一个.cpp对应一个...
  • 如果你不想让你的源代码变得很难阅读的话,就请使用多个编译单元吧.(一个函数不能放到两个编译单元里面,但两个以上就可以分别放在一个单元,也就是cpp里面)那么就是一个.cpp对应一个.obj,然后将所有...
  • 以VS2010为例: 点击“工具”——》“选项”——》“项目和解决方案”,勾选下列选项后确定,切换cpp或.h文件时,在左侧“解决方案资源管理器”面板,将自动定位到对应的工程文件;
  • 关于c c++ .h .cpp .c

    千次阅读 2010-03-19 20:42:00
    基础: 一个.cpp对应一个obj,一个.obj就是一个编译单元,多个编译单元在链接的时候通过链接器链接,组成一个exe,就是一个程序。如果一个cpp需要另外一个cpp定义的函数,只需要在这个cpp中写上这个函数的声明就可以...
  • ICE中把ICE文件创建成HCPP

    千次阅读 2016-01-26 16:54:44
    步骤:进行到你的ICE目录下面,(在CMD中的),然后输入 slice2cpp ICE文件名.ice 这是生成HCPP的,如果 你的是其它 的版本,还可以找对对应的命令来生成。D:\softinstall\Program Files (x86)\ZeroC\Ice-...
  • // one *.h file can correspond two or more *.cpp files // or a class definition can distribute in more than one *.cpp files// part.h #ifndef PART_H #define PART_H#include <iostream>class A { public:
  • mainWindow.h mainWindow.cpp(父窗口) childWindow.h childWindow.cpp(子窗口) 其中子窗口由VS窗口向导创建。 在父窗口中按下按钮,子窗口显示,按下子窗口中按钮,赋值然后子窗口关闭,已经确定 子窗口...
  • mfc 实现一分文档对应多个视图

    千次阅读 2009-11-20 20:44:00
    1--首先创建想切换的两视图类(view类)比如:class CTestView1 : public CFormView{}class CTestView2 : public CView{}2--然后在xx.cpp文件中(XX代表工程名)即CxxApp类的cpp文件中包含切换的两类的头文件,...
  • 网络只包含到输出三检测头的部分,三检测头分别对应80,40,和20的栅格尺寸,因此需要对三种尺寸的检测头输出结果依次解析,具体的解析过程在parse_yolov5函数中进行了实现: //获取各层结果 vector<Rect> ...
  • 现在开始写项目了,你会发现我们一般都要写一个cpp对应的还得有一个h文件,那么为什么在C++中我们要这么做? .h就是声明,.cpp就是实现,而所谓分离式实现就是指“声明”和“定义”分别保存在不同的文件中,声明保...
  • 可以,但是要在对应的头文件中声明。 举例: //main.cpp string g_a = ""; int main(int argc,char **argv) { g_a = "abc";...// server.h ...最好的方式还是用一头文件里声明全局变量,其他cpp若使
  • 由于.h文件和 .cpp文件是在同一目录下,再加上文件数量较,如果手动的将.h文件导出会是件很麻烦的事。 步骤 选择指定的项目和Target 展开“Build Phases”下的“Copy Files”,点击红框3标注的+按钮 在红...
  • 1.在A.h 中声明: extern int a; 2.在A.cpp【注意和上面A.h对应】中定义: int a; 或 int a=0;\ 3.在其他源文件中直接访问即可 c.cpp中: a=10;
  • 其二,一般我们在类中使用静态,而类的书写格式是一.h文件对应.cpp实现文件。如果你的赋初值声明写在了.h文件中,那么就会报这错误。改正方法就是把声明移到.cpp文件中,问题得以解决(反正我的是这原因)...
  • 在之前的博客QInputDialog 使用方法中展示了利用...那么此时用QInputDialog就没法实现了,我们必须基于QDialog类重新写一类,可是只是一简单的值输入框,我们又不想为了它而生成对应的.cpp和.h,还有.u...

空空如也

空空如也

1 2 3 4 5 ... 13
收藏数 247
精华内容 98
热门标签
关键字:

多个cpp对应h