5 前向声明和定义

这个程序看似正常:

1.

#include <iostream>

int main()
{
    std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n';
    return 0;
}

int add(int x, int y)
{
    return x + y;
}

你会期望这个程序产生结果:

3和4之和为:7

但实际上,它根本无法编译!Visual Studio 产生以下编译错误:

add.cpp(5) : error C3861: 'add': identifier not found

这个程序不能编译的原因是编译器按顺序编译代码文件内容,当编译器在main的的第五行调用add函数时,它不知道add是什么,因为下面才第九行才定义add,所以会参数错误。

2.

#include <iostream>

int add(int x, int y)
{
    return x + y;
}

int main()
{
    std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n';
    return 0;
}

这样,当main调用add时,编译器就已经知道add是什么了。

针对第一个程序,我们可以使用前置声明来解决这个问题,前置声明会在在实际定义标识符之前告诉编译器标识符的存在。对于函数,这允许我们在定义函数体之前告诉编译器函数的存在。这样,当编译器遇到对函数的调用时,它会明白我们正在调用函数,并且可以检查以确保我们正确调用函数,即使它还不知道如何或在哪里功能已定义。

要为函数编写前向声明,我们使用称为函数原型的声明语句。函数原型由函数的返回类型、名称、参数组成,但没有函数体(花括号和它们之间的所有内容),以分号结尾。

这是add函数的函数原型:

int add(int x, int y); //函数原型包括返回类型、名称、参数和分号,没有函数体

程序如下:

#include <iostream>

int add(int x, int y); // 前置声明

int main()
{
    std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n';  
    return 0;
}

int add(int x, int y) // 在这之前即使没有函数体被定义
{ 
    return x + y;
}

现在,当编译器到达main 中的add调用时,它会知道add是什么样子(一个接受两个整数参数并返回一个整数的函数)。

值得注意的是,函数原型不需要指定参数的名称。在上面的代码中,您还可以像这样转发声明您的函数:

int add(int, int);

忘记函数体

新程序员经常想知道如果他们转发声明一个函数但没有定义它会发生什么。

答案是:视情况而定。如果进行了前向声明,但从未调用过该函数,则程序将编译并正常运行。但是,如果进行了前向声明并调用了该函数,但程序从未定义该函数,则程序将正常编译,但链接器会抱怨它无法解析函数调用。

#include <iostream>

int add(int x, int y); // forward declaration of add() using function prototype

int main()
{
    std::cout << "The sum of 3 and 4 is: " << add(3, 4) << '\n';
    return 0;
}

// note: No definition for function add

在这个程序中,我们转发声明add,并调用add,但我们从未在任何地方定义add。当我们尝试编译这个程序时,Visual Studio 会产生以下消息:

正在编译...
添加.cpp
正在链接...
add.obj:错误 LNK2001:无法解析的外部符号“int __cdecl add(int,int)”( ?add@ @ YAHHH@Z )
add.exe : 致命错误 LNK1120: 1 unresolved externals

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值