让我详细说明我要做的事情,我需要将我的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不是类栏的成员
我的问题是:我做错了什么,有没有更好的方法去做我想做的事情?
提前谢谢你。
这段代码中存在不止一种误解。也许完全纠正它们比单独描述和讨论它们更容易。
让我们从依赖关系树的底部开始。下面是一个虚拟类
#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
您永远不应该
在预处理器阶段,编译器接受所有的 创建对象文件时,编译器使用头文件检查名称和类型,但不需要实际的定义。找到的定义被编译到目标文件中。分离对象文件的目的是将这些定义的编译分离成模块化的单元。