提问者:小点点

将C++源文件分离为多个文件的问题


让我详细说明我要做的事情,我需要将我的foo-bar程序拆分成五个单独的文件:main,foo.h,foo.cpp,bar.h,bar.cpp。我的头文件(foo.h和bar.h)旨在包含对应类的声明,而C++文件(foo.cpp和bar.cpp)旨在定义类。

我使用的是Visual Studio,到目前为止,唯一显示红旗的文件是我的主文件。下面是我到目前为止的代码,我将在主文件中包含正在抛出的错误:

main.cpp

#include <iostream>
#include "foo.h"
#include "foo.cpp"
#include "bar.h"
#include "bar.cpp"
using namespace std;

int main() {
   Bar b(25); /*I am getting a red flag under the 25, stating there is no constructor that can convert int to Bar*/

   b.func1(); /*I'm getting a red flag under func1 and func2 stating neither of them are members of Bar*/
   b.func2(34);

   return 0;}

FOO.H

#ifndef foo_h
#define foo_h
#include "foo.cpp"
 class Foo {};
#endif

foo.cpp

#ifndef foo_c
#define foo_c

#include "foo.h"
#include "bar.cpp"
private:
    int data;
public:
Foo(int d) : data(d) {}

int get_data() { return data; }

virtual void func1() = 0;

virtual int func2(int d) = 0;


#endif

Bar.H

#ifndef bar_h
#define bar_h
#include "bar.cpp"
#include "foo.h"
class Bar : public Foo {};
#endif

bar.cpp

#ifndef bar_c
#define bar_c

#include "bar.h"
#include "foo.h"
#include "foo.cpp"

Bar(int d) : Foo(d) {}

void func1() {
    cout << "Inside func1\n";
    cout << "\tData is " << get_data() << endl;
}

int func2(int d) {
    cout << "Inside func2 with " << d << endl;
    cout << "\tData is " << get_data() << endl;
    return d;
}

#endif

我的程序在我拆分它之前一直工作,但是现在当我试图编译它时,它总是向我抛出这个消息,并且在我的主代码中有两个红旗。控制台告诉我:

不存在将int转换为Bar的合适构造函数

func1不是类栏的成员

func2不是类栏的成员

我的问题是:我做错了什么,有没有更好的方法去做我想做的事情?

提前谢谢你。


共2个答案

匿名用户

这段代码中存在不止一种误解。也许完全纠正它们比单独描述和讨论它们更容易。

让我们从依赖关系树的底部开始。下面是一个虚拟类。这是它的正确声明。

#ifndef foo_h
#define foo_h
class Foo {
private:
    int data;
public:
   Foo(int);
   int get_data();
   virtual void func1() = 0;
   virtual int func2(int) = 0;
 };

#endif

注意,我们在头文件中包含了它的所有方法的声明。但是,非虚拟方法的实现被移到文件中。

#include "foo.h"

Foo::Foo(int d) : data(d) { }

int Foo::get_data() { return data; }

请注意,我们不需要任何特殊的设备来防止文件的多重包含,因为我们永远不会包含它。

现在是为我们做一些实际工作的类的父类。同样,它的所有方法都在类声明中声明。

#ifndef bar_h
#define bar_h
#include "foo.h"
class Bar : public Foo {
public:
   Bar(int);
   void func1();
   int func2(int);
};
#endif

它的实现在相应的名为的编译单元中。当实现一个类方法时,我们通过在方法名之前加上类名来指示该方法属于哪个类,例如

#include "bar.h"
#include "foo.h"

#include <iostream>

Bar::Bar(int d) : Foo(d) {};

using namespace std;

void Bar::func1() {
    cout << "Inside func1\n";
    cout << "\tData is " << get_data() << endl;
}

int Bar::func2(int d) {
    cout << "Inside func2 with " << d << endl;
    cout << "\tData is " << get_data() << endl;
    return d;
}

最后,我们在中使用它,其中只需要做一点小的更改。

#include <iostream>
#include "foo.h"
#include "bar.h"
using namespace std;

int main() {
   Bar b(25); 

   b.func1(); 
   b.func2(34);

   return 0;}

现在让我们继续建设我们的项目。如果您使用的是GCC,那么很容易将其描述为一系列CLI命令。由于您使用的是Visual Studio,因此必须通过GUI执行相应的操作。

>

下一个编译栏

编译主程序

现在把它们连在一起

最后运行它,瞧

    Inside func1
        Data is 25
    Inside func2 with 34
        Data is 25

匿名用户

您永远不应该文件。相反,将每个文件编译成一个对象文件,并将它们链接到一个可执行文件中。

在预处理器阶段,编译器接受所有的

创建对象文件时,编译器使用头文件检查名称和类型,但不需要实际的定义。找到的定义被编译到目标文件中。分离对象文件的目的是将这些定义的编译分离成模块化的单元。

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|源文件|分离|多个|文件)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?