函数签名(Function Signature)

函数签名(Function Signature)是指函数的名称及其参数类型的组合。函数签名用于标识和区分不同的函数。函数签名不包括返回类型,也不包括参数的名字。两个函数如果名称相同且参数类型(及其顺序)相同,那么它们的函数签名是相同的。

组成部分

  1. 函数名称:函数的标识符。
  2. 参数类型:函数参数的类型列表,包括参数的顺序。

作用

  • 重载(Overloading):在 C++ 中,可以定义多个同名但参数类型或数量不同的函数,这称为函数重载。函数签名用于区分这些重载函数。
  • 匹配(Matching):编译器使用函数签名来匹配函数调用和定义。

示例

#include <iostream>

// 函数重载示例

void print(int a) {
    std::cout << "Integer: " << a << std::endl;
}

void print(double a) {
    std::cout << "Double: " << a << std::endl;
}

void print(const std::string& a) {
    std::cout << "String: " << a << std::endl;
}

int main() {
    print(42);              // 调用 print(int)
    print(3.14);            // 调用 print(double)
    print("Hello, world");  // 调用 print(const std::string&)

    return 0;
}

在这个示例中,print 函数被重载了三次,每个函数的签名不同:

  • void print(int a) 的签名是 print(int)
  • void print(double a) 的签名是 print(double)
  • void print(const std::string& a) 的签名是 print(const std::string&)

尽管这些函数的名字相同,但由于它们的参数类型不同,编译器可以区分它们。

函数签名不包括的内容

  • 返回类型:函数的返回类型不包含在函数签名中。这意味着你不能仅通过改变返回类型来重载函数。
int func(int a);    // 函数签名是 func(int)
double func(int a); // 编译错误:与前面的函数签名相同
  • 参数名:参数名在函数签名中也不重要,因此在函数声明中可以省略参数名。
void foo(int, double); // 函数签名是 foo(int, double)
void foo(int a, double b); // 函数签名也是 foo(int, double)

具体应用场景

1. 函数重载

函数签名在函数重载中尤为重要。如下示例展示了如何使用相同函数名但不同参数类型和数量来实现重载。

#include <iostream>

void display(int a) {
    std::cout << "Integer: " << a << std::endl;
}

void display(double a) {
    std::cout << "Double: " << a << std::endl;
}

void display(int a, double b) {
    std::cout << "Integer and Double: " << a << ", " << b << std::endl;
}

int main() {
    display(42);           // 调用 display(int)
    display(3.14);         // 调用 display(double)
    display(42, 3.14);     // 调用 display(int, double)

    return 0;
}

2. 函数指针

函数签名也用于函数指针的类型定义。

#include <iostream>

// 定义一个函数类型
typedef void (*FuncType)(int, double);

// 定义一个函数
void exampleFunction(int a, double b) {
    std::cout << "a: " << a << ", b: " << b << std::endl;
}

int main() {
    // 声明一个函数指针并指向 exampleFunction
    FuncType funcPtr = exampleFunction;
    // 使用函数指针调用函数
    funcPtr(10, 20.5);

    return 0;
}

总结

  • 函数签名 包含函数名称和参数类型列表,但不包括返回类型和参数名。
  • 函数重载 通过不同的参数类型或参数数量来实现,依赖于函数签名来区分不同的函数。
  • 函数指针 也使用函数签名来定义类型,从而指向特定签名的函数。

理解函数签名的概念对于掌握 C++ 的函数重载和指针等高级特性至关重要。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`permit`函数需要传入签名的v、r、s值,这些值可以通过以下步骤获取: 1. 使用代币持有者的私钥对授权信息进行签名,得到一个签名数据。 2. 使用签名数据提取出v、r、s值。 具体步骤如下: 1. 组装签名数据 签名数据需要包含以下字段: - `address owner`: 代币持有者地址。 - `address spender`: 授权的代币接收地址。 - `uint256 value`: 授权的代币数量。 - `uint256 nonce`: 代币持有者的nonce值,用于防止重放攻击。 - `uint256 deadline`: 授权的截止时间戳,用于提高安全性。 - `uint256 chainId`: 链ID,用于区分不同的链。 - `address tokenAddress`: 代币合约地址。 具体代码如下: ```solidity function getPermitHash( address owner, address spender, uint256 value, uint256 nonce, uint256 deadline, uint256 chainId, address tokenAddress ) public pure returns (bytes32) { bytes32 hash = keccak256( abi.encodePacked( bytes1(0x19), bytes1(0x01), chainId, tokenAddress, keccak256( abi.encode( "permit", owner, spender, value, nonce, deadline ) ) ) ); return hash; } ``` 其中,`chainId`是链ID,用于区分不同的链。`tokenAddress`是代币合约地址。`nonce`是代币持有者的nonce值,可以从`ERC20`合约的`nonce`函数获取。 2. 对签名数据进行签名 使用代币持有者的私钥对签名数据进行签名,得到一个签名数据。可以使用钱包或其他工具实现签名功能。 3. 提取v、r、s值 使用签名数据提取出v、r、s值,可以使用以下代码实现: ```solidity function splitSignature(bytes memory signature) public pure returns (uint8 v, bytes32 r, bytes32 s) { require(signature.length == 65, "invalid signature length"); assembly { r := mload(add(signature, 32)) s := mload(add(signature, 64)) v := byte(0, mload(add(signature, 96))) } if (v < 27) { v += 27; } require(v == 27 || v == 28, "invalid signature value"); return (v, r, s); } ``` 例如,以下是一个完整的获取签名数据的示例代码: ```solidity IERC20 token = IERC20(0x123456...); // 代币合约地址 address owner = 0xabcdef...; // 代币持有者地址 address spender = 0x789abc...; // 授权的代币接收地址 uint256 value = 100; // 授权的代币数量 uint256 deadline = block.timestamp + 3600; // 授权的截止时间戳 uint256 nonce = token.nonces(owner); // 代币持有者的nonce值 uint256 chainId = 1; // 链ID bytes32 hash = getPermitHash(owner, spender, value, nonce, deadline, chainId, address(token)); // 获取签名hash bytes memory signature = signMessage(hash, ownerPrivateKey); // 对签名hash进行签名 (uint8 v, bytes32 r, bytes32 s) = splitSignature(signature); // 提取v、r、s值 token.permit(owner, spender, value, deadline, v, r, s); // 调用permit函数 ``` 其中,`signMessage`函数是使用代币持有者的私钥对签名hash进行签名函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王成长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值