这应该是很偶然的,我只是想不出如何将源代码分成不同的文件。
当我将代码编写为单个源文件时,我的代码可以编译并执行得很好:
#include <iostream>
using namespace std;
class Greeter{
public:
void greet();
};
void Greeter::greet(){
cout << "Hello World!";
}
int main(){
Greeter greeter;
greeter.greet();
return 0;
}
但是请尝试将代码分成单独的源文件:
Greeter.h
#include <iostream>
using namespace std;
class Greeter{
public:
Greeter();
void greet();
};
Greeter.cxx
#include <iostream>
#include "Greeter.h"
using namespace std;
void Greeter::greet(){
cout << "Hello World!";
}
main.cxx
#include <iostream>
#include "Greeter.h"
using namespace std;
int main(){
Greeter greeter;
greeter.greet();
return 0;
}
总是会导致编译错误:
main.cxx:(.text+0x16): undefined reference to `Greeter::Greeter()'
答案 0 :(得分:4)
目前尚不清楚这些评论是否解决了您的问题。在将源分成标题和多个源时,该错误证明的主要问题是,您在class Greeter
中包含了Greeter.h
的不完整构造函数。具体来说,您无法包含“空参数列表” 来完成构造函数,例如
Greeter() {}; /* default construct */
请参见cppreference - Default constructors
您应避免的下一个问题是在头文件中包含using namespace std;
。参见“using namespace” in c++ headers。相反,只需调用cout
,std::cout
,而无需完全包含名称空间。
接下来,尽管iostream
具有适当的标题保护,但您只需要将其包括在Greeter.cpp
中(这是唯一使用iostream
函数的源)。您还应该在Greeter.h
中包括标头保护符,以防止在编译过程中包含多个内容。只需创建一个#define
并检查是否已经在标头中定义了该标头,例如
greeter.h
#ifndef my_class_greeter_h
#define my_class_greeter_h 1
class Greeter {
public:
Greeter() {}; /* default construct */
void greet();
};
#endif
现在,如果已经定义了greeter.h
,则每个包含my_class_greeter_h
的文件都将避免再次包含它。
greeter.cpp
带有类函数定义的源文件是唯一依赖iostream
调用的源文件,并且是唯一需要#include <iostream>
的文件,例如
#include <iostream>
#include "greeter.h"
void Greeter::greet(){
std::cout << "Hello World!\n";
}
main.cpp
您main.cpp
源文件只需要包含包含类定义的标头,例如
#include "greeter.h"
int main (void) {
Greeter greeter; /* instantiate greeter */
greeter.greet(); /* call greet() */
return 0;
}
两个源都必须编译
要编译单独的源文件,需要同时编译main.cpp
和greeter.cpp
(编译greeter.cpp
以使其成为对象,或者仅将两个.cpp
文件都包含在编译字符串中)
使用gcc/clang
$ g++ -Wall -Wextra -pedantic -std=c++11 -Ofast -o main main.cpp greeter.cpp
使用VS(cl.exe
)编译
> cl /nologo /W3 /Ox /EHsc /Femain /TP main.cpp greeter.cpp
(在没有警告的情况下编译之前,不接受代码)
使用/输出示例
在任何一种情况下,输出均符合预期:
$ ./main
Hello World!
仔细检查一下,如果还有其他问题,请告诉我。