用正常函数分离接口和实现

时间:2010-04-27 08:02:39

标签: c++

这看起来应该很简单,我可能会留下一些简单的东西。

这是我正在尝试运行的代码。它是3个文件,2 * cpp和1 *标题。

这不会在代码块上运行,我正试着看看我错过了什么!

这些是给出的错误:

obj \ Debug \ main.o ||在函数`main'中:|

| 9 |对“generateArray(int *,int)”|

的未定义引用

| 11 |未定义引用`reverseOrder(int *,int *,int)'|

| 13 |对`displayArray(int *,int *,int)'|

的未定义引用
// lab6.h
#ifndef LAB6_H_INCLUDED
#define LAB6_H_INCLUDED

int const arraySize = 10;
int array1[arraySize];
int array2[arraySize];

void generateArray(int[], int );
void displayArray(int[], int[], int );
void reverseOrder(int [],int [], int);

#endif // LAB6_H_INCLUDED

// lab6.cpp

#include "lab6.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using std::cout; using std::endl;
using std::rand; using std::srand;
using std::time;
using std::setw;

void generateArray(int array1[], int arraySize)
{
    srand(time(0));
    for (int i=0; i<10; i++)
    {
        array1[i]=(rand()%10);
    }
}

void displayArray(int array1[], int array2[], int arraySize)
{
    cout<<endl<<"Array 1"<<endl;
    for (int i=0; i<arraySize; i++)
    {
        cout<<array1[i]<<", ";
    }
    cout<<endl<<"Array 2"<<endl;
    for (int i=0; i<arraySize; i++)
    {
        cout<<array2[i]<<", ";
    }
}

void reverseOrder(int array1[],int array2[], int arraySize)
{
    for (int i=0, j=arraySize-1; i<arraySize;j--, i++)
    {
        array2[j] = array1[i];
    }
}

// and finally main.cpp
#include "lab6.h"

int main()
{
    generateArray(array1, arraySize);
    reverseOrder(array1, array2, arraySize);
    displayArray(array1, array2, arraySize);
    return 0;
}

4 个答案:

答案 0 :(得分:1)

从链接器的错误消息中得出结论,您似乎没有为链接器提供对象文件,并且它无法找到您在{{1}中定义的内容}。我不知道CodeBlocks,所以我不知道如何设置项目以便链接器传递所有目标文件。
但是,大多数编译器会使用它们生成的所有目标文件调用链接器,因此手动调用编译器

lab6.cpp

(用你的编译器代替“cc”)可能会这样做。

无论如何,一旦你管理了它,你仍然会有链接器错误,因为你的阵列 在标题 中定义,这使得它们 结束两个翻译单元 。链接器会抱怨 重复符号

除此之外,我批评那个

  • 你使用全局变量而不是本地变量(一旦修复了它,它们也不再在两个翻译单元中定义),
  • 如果您更改cc lab6.cpp main.cpp (因为您没有在任何地方使用过它),代码会爆炸,
  • 您使用arraySize指定数组的大小,而不是int
  • 您使用C数组而不是C ++容器(这可能是必需的,因为这是作业)。

哦,如果需要,我会删除所有使用std::size_t的声明和前缀标识符。在你的情况下,它甚至可以节省打字。此外,它使代码更清晰(有些人会反对这一点)而且它更少error prone(很难反驳)。

答案 1 :(得分:0)

不,你没有。 你有两个cpp文件,包含

int array1[arraySize];
int array2[arraySize];

lib6.cpp和main.cpp正常编译但duranig链接当然有一个错误:“array1的多重定义...”

答案 2 :(得分:0)

首先,从头文件中取出以下代码片段:

int const arraySize = 10;
int array1[arraySize];
int array2[arraySize];

在主函数内移动上面的代码。如果你把它们放在头文件中,你就把它们变成了全局变量,这是一个非常糟糕的主意。此外,由于这些是定义,而不是声明,它们将被多次创建(每个编译单元一次 - 即.cpp源文件 - 包括标题),如果你是这样的话会导致多重定义错误将“lab6.o”和“main.o”链接在一起。

其次,看来您已将“main.cpp”编译为“main.o”但是您忘记将“lab6.cpp”编译为“lab6.o”并将“lab6.o”链接到“ main.o“,在一起。我不知道怎么用Code :: Blocks做这个,虽然我怀疑它涉及检查“lab6.cpp”,以便它包含在构建中。如果您愿意使用命令行进行构建并拥有g ++编译器,那么您可以使用:

g++ main.cpp -c -o main.o
g++ lab6.cpp -c -o lab6.o
g++ main.o lab6.o -o lab6

通过上述内容,您可以调用./lab6来运行您的程序。您可能希望使用构建系统(如CMake或Make(我建议使用CMake))来构建程序,而不是依赖于Code :: Blocks。

此外,假设您被允许这样做,建议您使用std::vector而不是原始数组。当然,您的任务可能要求您使用常规数组,在这种情况下,这是不可能的。此外,通常最好使用std :: size_t而不是int作为索引类型,虽然int可以工作,如果你使用std :: size_t(无符号),它可能会导致你的一些循环出现问题,所以相反根据其他一个回答者的建议,我建议你在这一点上坚持使用int(但是,将来你应该使用std :: size_t作为数组大小/索引类型)。

答案 3 :(得分:0)

在编写本机C ++代码时不要使用“using”指令,因为它会污染全局命名空间。

如何用命名约定来区分常量?对于常量和枚举,如何使用ARRAYSIZE而不是arraySize

为什么您的数组在头文件中?你的函数是为了在main()中使用“user”。有了这个实现,用户就无法改变ARRAYSIZE。事实上,当函数被设计为使用任意大小的数组时,是否还需要ARRAYSIZE?

通过指针传递数组,传递值更慢且更昂贵

lab6.cpp

#include "lab6.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
//#include <iomanip>

void generateArray(int* array1, int arraySize)
{
    // make implicit type conversions explicit
    std::srand((unsigned)std::time(0));
    // why the magic number here?
    for (int i=0; i<10; i++)
    {
        array1[i]=(std::rand()%10);
    }
}

void displayArray(int* array1, int* array2, int arraySize)
{
    std::cout << std::endl << "Array 1" << std::endl;
    for (int i=0; i<arraySize; i++)
    {
        std::cout<<array1[i]<<", ";
    }
    std::cout << std::endl << "Array 2" << std::endl;
    for (int i=0; i<arraySize; i++)
    {
        std::cout<<array2[i]<<", ";
    }
}

void reverseOrder(int* array1, int* array2, int arraySize)
{
    // This is hard to read, and why do you need another integer anyway
    // for (int i=0, j=arraySize-1; i<arraySize;j--, i++)
    // {
        // array2[j] = array1[i];
    // }

    for(int i=0;i<arraySize;i++)
    {
        array2[arraySize - i - 1] = array1[i];
    }
}

lab6.h

#ifndef LAB6_H_INCLUDED
#define LAB6_H_INCLUDED

void generateArray(int* array1, int arraySize);
void displayArray(int* array1, int* array2, int arraySize);
void reverseOrder(int* array1, int* array2, int arraySize);

#endif // LAB6_H_INCLUDED

的main.cpp

#include "lab6.h"
int main()
{
    int const arraySize = 10;
    int array1[arraySize];
    int array2[arraySize];

    generateArray(array1, arraySize);
    reverseOrder(array1, array2, arraySize);
    displayArray(array1, array2, arraySize);

    return 0;
}