全网最通俗易懂c3线性化讲解,继承讲解

  • oo
  • 更新于 4天前
  • 阅读 112

本文主要讲不规则继承下合约的插槽问题和调用函数问题钻石继承的插槽问题试问现在有上图这样的继承关系,abcd中各有一个变量,请问他们在插槽中的顺序是什么样的这要取决于D是在继承bc时的写法contractDisB,C{如果是这样写的,那么b的变量就排在c的变量前面,此时可以把c当


title: 继承 date: 2024-06-13 16:58 tags: null


本文主要讲不规则继承下合约的插槽问题和调用函数问题

钻石继承的插槽问题

9cd95730198cf78c1fa3a541bf10a954.png

试问现在有上图这样的继承关系,abcd中各有一个变量,请问他们在插槽中的顺序是什么样的

这要取决于D是在继承bc时的写法

contract D is B ,C{

如果是这样写的,那么b的变量就排在c的变量前面,此时可以把c当作b的父合约,如果想使用b中的变量,就需要两个super,但仅限于在d合约中是这样

pragma solidity ^0.8.22;
import "hardhat/console.sol";

contract A{

string public  a;

function setString(string memory m) external virtual  {
a=m;
}

function setTime()public  virtual {
console.log(unicode"a");
}

}

contract B is A{

string public  b;

function setString(string memory m) external override virtual  {
b=m;
}

function setTime()public  override virtual  {
console.log(unicode"b");
}

}

contract C is A{

string public c;

function setString(string memory m) external    override virtual  {
c=m;
}

function logFather() external {
    super.setTime();//b
}

}

contract D is B ,C{

string public  d;
E e;

function setString(string memory m) external override(B,C)  {
d=m;
}

function dele(address ee,uint num)external returns (bytes memory){
(bool iscom,bytes memory data)=ee.delegatecall(abi.encodeWithSignature("hootString(uint256)",num));
return  data;
}
//每一个函数都必须
function setTime()public  override (B,A) {//必须指名所有直接基类合约
console.log(unicode"d");
}

}

验证:我们编译部署上面的合约,并调用logFather函数,得到的结果是b b2bcf7773dd7f12e46c08af0b35b732e.pngAlt text e45b45471cfeeed693e9032466e8853b.png

如果是更复杂的继承关系,该如何确定呢? 这里需要介绍c3线性化 2fa3499b0a168c6bda3e6f2a9a8f573e.png以这个图中的继承关系为例,我们如何确定继承的顺序

令L(x)=[x]+merge(L(a),L(b),L[c]...,[a,b,c...])//其中abc都是x的直系父合约

那么图中
 L(O)  := [O]                                             

 L(A)  := [A] + merge(L(O), [O])                            
        = [A] + merge([O], [O])
        = [A, O]                                           

 L(B)  := [B, O]                                            
 L(C)  := [C, O]
 L(D)  := [D, O]
 L(E)  := [E, O]
 L(K1) := [K1] + merge(L(C), L(B), L(A), [C, A, B]) 
  = [K1] + merge([C, O], [B, O], [A, O], [C, A, B]) //如果某个元素在merge数组中仅作为第一个元素,那么这个元素会被提取出来,比如这里的c,在第一个和最后一个数组中都是第一个元素,且其他数组没有c,那么c就会被提取出来,放在前面  
        = [K1, C] + merge([O], [B, O], [A, O], [A, B])     
        = [K1, C, A] + merge([O], [B, O], [O], [B])         
        = [K1, C, A, B] + merge([O], [O], [O])             
        = [K1, C, A, B, O]

         L(K3) := [K3] + merge(L(A), L(D), [A, D])
        = [K3] + merge([A, O], [D, O], [A, D])               // select A
        = [K3, A] + merge([O], [D, O], [D])                  // fail O, select D
        = [K3, A, D] + merge([O], [O])                       // select O
        = [K3, A, D, O]

 L(K2) := [K2] + merge(L(B), L(D), L(E), [B, D, E])
        = [K2] + merge([B, O], [D, O], [E, O], [B, D, E])    // select B
        = [K2, B] + merge([O], [D, O], [E, O], [D, E])       // fail O, select D
        = [K2, B, D] + merge([O], [O], [E, O], [E])          // fail O, select E
        = [K2, B, D, E] + merge([O], [O], [O])               // select O
        = [K2, B, D, E, O]

 L(Z)  := [Z] + merge(L(K1), L(K3), L(K2), [K1, K3, K2])
        = [Z] + merge([K1, C, A, B, O], [K3, A, D, O], [K2, B, D, E, O], [K1, K3, K2])    // select K1
        = [Z, K1] + merge([C, A, B, O], [K3, A, D, O], [K2, B, D, E, O], [K3, K2])        // select C
        = [Z, K1, C] + merge([A, B, O], [K3, A, D, O], [K2, B, D, E, O], [K3, K2])        // fail A, select K3
        = [Z, K1, C, K3] + merge([A, B, O], [A, D, O], [K2, B, D, E, O], [K2])            // select A
        = [Z, K1, C, K3, A] + merge([B, O], [D, O], [K2, B, D, E, O], [K2])               // fail B, fail D, select K2
        = [Z, K1, C, K3, A, K2] + merge([B, O], [D, O], [B, D, E, O])                     // select B
        = [Z, K1, C, K3, A, K2, B] + merge([O], [D, O], [D, E, O])                        // fail O, select D
        = [Z, K1, C, K3, A, K2, B, D] + merge([O], [O], [E, O])                           // fail O, select E
        = [Z, K1, C, K3, A, K2, B, D, E] + merge([O], [O], [O])                           // select O
        = [Z, K1, C, K3, A, K2, B, D, E, O]  
        最后得到的这个数组就是继承顺序,可以看到,第一排merge中的顺序是根据继承时写的顺序来的       
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
oo
oo
关注我,带你深入研究solidity机制,熟悉各种安全库和链上攻击