📜 [專欄新文章] Solidity Weekly #12
✍️ mingderwang
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
functions 什麼時候用 external、private、或 internal
function 跟 (storage) state 全區域合約變數預設不同,變數宣告只有在 public 才會對外開放,讓別人看得到值;而 function 剛好相反,預設是 public。也就是說你沒刻意去宣告,它是可以被外面的程式或合約呼叫。
但如果你刻意用 external、private、或 internal 來宣告 function 的被 call 的屬性,能對最佳化得到一些好處。而 public 與 external 都會讓 function 公開;相反的 internal 與 private 的 functions 只能被合約內部叫用。
限制多寡的順序是︰ public < external < internal < private。
公開 use cases︰
比如說,如果你確定不對內公開,最好宣告為 external。external 有個好處是 call 的參數是從 CALLDATA 獲得,不需要 copy 到 memory 才能執行該 function call。所以比較省 gas,尤其是處理參數是 array 時更凸顯其效果。
但用 external,自己合約如果要調用,反而要寫 this.f() 編譯器才能接受,通常是多此一舉。而且會呼叫 CALL 指令,跟 JUMP 指令比,花更多 gas。
不公開 use cases︰
當合約自己內部的 functions 不想被外部合約或程式調用,最好是用 internal 或甚至用 private 來做限制。internal 還可以被繼承的合約來調用,而 private 就只能自己合約內使用。
它們會被用 JUMP 指令來呼叫,比較省 gas。
我們用 StackOverflow 的範例來做測試,改寫成 Test.sol 如下;
// Test.sol pragma solidity^0.4.12;
contract Test {
// spend 662 gasfunction test(uint[20] a) public pure returns (uint) { return a[10] * 2; }
// spend 317 gasfunction test2(uint[20] a) external pure returns (uint) { return a[10] * 2; }
function test3(uint[20] a) internal pure returns (uint) { return a[10] * 2; } function test4(uint[20] a) private pure returns (uint) { return a[10] * 2; }}
測試程式 (DoTest.sol) 如下︰
// DoTest.solpragma solidity ^0.4.18;
import "./Test.sol";
contract DoTest is Test {uint[20] a;uint public xx;
constructor() public { a[10]=3; } function test_1() external returns(uint) { xx = test(a); return xx; } function test_2() external returns(uint) { xx = this.test2(a); // <-- use this. return xx; } function test_3() external returns(uint) { xx = test3(a); return xx; } function test_4() external returns(uint) { xx = test4(a); // <-- compile error return xx; }}
如果你用 remix 測試,會發現 DoTest 測試繼承 Test 來的不同宣告方式的 functions,會有不同的效果。且 test3() 跟 test4() 對外是看不到的。
links 分享;
Learn X in Y minutes, where X = Solidity Ming> 雖然所用的 solidity 版本 ^0.4.19 還有點舊,但註解做得很好,值得初學者參考。
Ethernaut Lvl 12 Privacy Walkthrough: How Ethereum optimizes storage to save space and be less gassy — (Nicole Zhu) Ming > Coinmonks 的 Medium 裡還有其他很多非常精彩的文章,請自己來尋寶。
The Ethernaut by Zeppelin Ming> 一個 web3/solidity 闖關遊戲平台。
Solidity Weekly #12 was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
同時也有10000部Youtube影片,追蹤數超過2,910的網紅コバにゃんチャンネル,也在其Youtube影片中提到,...
「copy constructor範例」的推薦目錄:
- 關於copy constructor範例 在 Taipei Ethereum Meetup Facebook 的最佳貼文
- 關於copy constructor範例 在 コバにゃんチャンネル Youtube 的精選貼文
- 關於copy constructor範例 在 大象中醫 Youtube 的最讚貼文
- 關於copy constructor範例 在 大象中醫 Youtube 的最讚貼文
- 關於copy constructor範例 在 [問題] default constructor - 精華區C_and_CPP - 批踢踢實業坊 的評價
- 關於copy constructor範例 在 《STUST OCW》物件導向程式設計_Copy Constructor (複製 ... 的評價
- 關於copy constructor範例 在 C++的Class中的一些重點整理 - Jason Blog 的評價
- 關於copy constructor範例 在 [HW#1] Q&As - Facebook 的評價
copy constructor範例 在 《STUST OCW》物件導向程式設計_Copy Constructor (複製 ... 的推薦與評價

課程主題:物件導向程式設計_ Copy Constructor (複製建構元) and Assignment Operator (設定運算) - 簡易實作版課程 ... ... <看更多>
copy constructor範例 在 C++的Class中的一些重點整理 - Jason Blog 的推薦與評價
問題點出在 pass by value 的時候並不是直接用等號來作assignment,而是會先呼叫copy constructor。 假設有一個function foo長這樣 //pass by reference foo(Bar bar). ... <看更多>
copy constructor範例 在 [問題] default constructor - 精華區C_and_CPP - 批踢踢實業坊 的推薦與評價
所謂deflaut consructor
是指沒有宣告 constrcutor的時候,complier會自動幫我們宣告
1.empty constructor
2.copy constructor
第一個問題
我想請問
什麼叫做 沒有宣告contructor
是指
在class中
沒有宣告constructor( )的參數嗎
還是指
在class中
沒有宣告consructor
第2個問題
什麼是copy constructor
那有什麼用處的
我在網路在 看到一個範例
class CExample {
public:
int a,b,c;
void multiply (int n, int m) { a=n; b=m; c=a*b; };
};
CExample::CExample (const CExample& rv) {
a=rv.a; b=rv.b; c=rv.c;
}// 這一段 似乎 就是copu constructor的寫法
不過 我在做編譯的時候
complier不給我過
他說 要在class中 宣告constructor;
不過當我宣告以後
class CExample {
public:
int a,b,c;
CExmple();
void multiply (int n, int m) { a=n; b=m; c=a*b; };
};
complier 依然顯示相同的錯誤。
請問 是哪裡有錯???
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.114.130.131
> -------------------------------------------------------------------------- <
作者: UNARYvvv (有趣生活) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Tue Jun 21 23:06:47 2005
※ 引述《wearebest (加油)》之銘言:
: complier不給我過
: 他說 要在class中 宣告constructor;
: 不過當我宣告以後
: class CExample {
: public:
: int a,b,c;
: CExmple();
因為以上叫做 default constructor
而且你拼錯了,上面那行函式名稱跟 class 名稱不一樣
(所以事實上拼得不一樣..也根本就不叫 constructor 哩XD)
copy constructor 的宣告應該長這樣:
CExample(const CExample &rhs);
一個參數,型態為本身類別
這表示你在建立一個新 CExample 物件時
能根據另一個 CExample 物件的內容來作初始化
我不確定那個參數如果不是 const reference 會不會編譯錯誤
但是照著這種標準寫法來寫準沒錯
: void multiply (int n, int m) { a=n; b=m; c=a*b; };
: };
: complier 依然顯示相同的錯誤。
: 請問 是哪裡有錯???
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.59.30.19
> -------------------------------------------------------------------------- <
作者: aoc90058 (我是新警察Orz...) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Tue Jun 21 23:33:06 2005
※ 引述《wearebest (加油)》之銘言:
: 所謂deflaut consructor
: 是指沒有宣告 constrcutor的時候,complier會自動幫我們宣告
: 1.empty constructor
這有些像...
sort( v.begin(),v.end(),greater<unsigned int> () );
雖然說greater它並不需要引入啥東西在data做比較的動作
但他會有一個deflaut constructor 所以你還是得打出來
: 2.copy constructor
class CExample {
private:
int a,b,c;
//恕我修改到private
public:
CExample(const CExample& rv);
void multiply (int n, int m) { a=n; b=m; c=a*b; };
};
CExample::CExample (const CExample& rv) {
a=rv.a; b=rv.b; c=rv.c;
}
這樣我是能夠編譯成功的
Microsoft Visual C++ Toolkit 2003
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.218.171.71
※ 編輯: aoc90058 來自: 61.218.171.71 (06/21 23:35)
> -------------------------------------------------------------------------- <
作者: Fightsea (蜂蜜派) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Wed Jun 22 06:47:32 2005
※ 引述《wearebest (加油)》之銘言:
: 所謂deflaut consructor
: 是指沒有宣告 constrcutor的時候,complier會自動幫我們宣告
雖如果你去查google 第一個網頁的確是這樣定義default consructor
但是default constructor應該是指具有default argument的constructor
"沒有宣告 constrcutor的時候,complier會自動幫我們宣告"
上面所寫的這個東西一般就直接叫做constructor
: 我想請問
: 什麼叫做 沒有宣告contructor
沒有宣告constructor 就是指你的class裡面沒有寫關於constructor的部份
跟參數無關 constructor可以沒有參數
: 什麼是copy constructor
: 那有什麼用處的
copy constructor是指當你新增一個物件的時候
想要用現有的某個物件的內容作為新物件的初始內容
則使用copy constructor
也就是假設有一個叫做House1的物件 我想要複製一棟房子的意思
House House1;
經過一些程式碼之後 House1中已經有很多member是有意義的資料
House House2( House1 ); //呼叫copy constructor
所以copy constructor的prototype如下
House( const House & ); //記得加const才符合copy的精神
然後你再自己去寫copy constructor的內容 讓House1的內容可以複製到House2中
--
建議你先把專有名詞的意思搞懂 再去看程式碼
如果觀念懂了 程式碼有寫錯通常只是一些資料型態或是指標在出錯
這樣你應該可以自己去偵錯了...
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.122.22.174
※ 編輯: Fightsea 來自: 140.122.22.174 (06/22 06:55)
※ 編輯: Fightsea 來自: 140.122.22.174 (06/22 06:57)
> -------------------------------------------------------------------------- <
作者: myselves (...) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Wed Jun 22 20:38:26 2005
※ 引述《wearebest (加油)》之銘言:
: 所謂deflaut consructor
: 是指沒有宣告 constrcutor的時候,complier會自動幫我們宣告
應該不是這樣的~~
default constructor是指物件被定義時,沒有提供建構氏參數
像是這樣的定義:
int a; 或者
MyClass myObject;
還有定義物件陣列的時候: MyClass myClassArray[100];
顯然的這些定義都沒有提供constructor參數,
所以程式就要呼叫一個不用參數的constuctor,
這個constructor就是default constructor。
只能有一個,但是不只有一種(compiler自動產生的那個只是其中一種)
Xxxxx(); 或 Xxxxx(int a = 3); 都是 (都可以不提供參數)
: 1.empty constructor
: 2.copy constructor
當定義一個物件並初始化為另一個物件時,例如
ClassA a;
ClassA b = a;
或者傳參數進函數的時候(call by value),都會進行memberwise copy
就是把data members一個對一個做複製
第一種情況如果沒有宣告copy constructor會變成
ClassA a;
ClassA b;
b = a; //呼叫operator=
這種情況會需要copy constructor通常是因為有data member是指標......
會造成兩個物件的data member(指標)指向同一塊記憶體
至於copy constructor為什麼要call by reference而不能call by value......
因為如果call by value的話,物件被傳進去是被複製一份新的,等於還要再
呼叫一次copy constructor,會導致遞迴 (這邊我形容的很爛,可能很難看的懂= =)
而copy constructor的型態未必要跟class本身一樣
例如 Xxxxx(const Yyyyy &rhs); 是可以的(通常都是Xxxxx(const Xxxxx &rhs);)
當
Yyyyy y;
Xxxxx x = y; //這時候 Xxxxx(const Yyyyy &rhs)會被呼叫
: 第一個問題
: 我想請問
: 什麼叫做 沒有宣告contructor
: 是指
: 在class中
: 沒有宣告constructor( )的參數嗎
: 還是指
: 在class中
: 沒有宣告consructor
: 第2個問題
: 什麼是copy constructor
: 那有什麼用處的
: 我在網路在 看到一個範例
: class CExample {
: public:
: int a,b,c;
: void multiply (int n, int m) { a=n; b=m; c=a*b; };
: };
: CExample::CExample (const CExample& rv) {
: a=rv.a; b=rv.b; c=rv.c;
: }// 這一段 似乎 就是copu constructor的寫法
: 不過 我在做編譯的時候
: complier不給我過
: 他說 要在class中 宣告constructor;
: 不過當我宣告以後
: class CExample {
: public:
: int a,b,c;
: CExmple();
: void multiply (int n, int m) { a=n; b=m; c=a*b; };
: };
: complier 依然顯示相同的錯誤。
: 請問 是哪裡有錯???
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.123.225.128
> -------------------------------------------------------------------------- <
作者: WanCW (笨狐狸) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Wed Jun 22 20:58:14 2005
※ 引述《myselves (...)》之銘言:
: 而copy constructor的型態未必要跟class本身一樣
: 例如 Xxxxx(const Yyyyy &rhs); 是可以的(通常都是Xxxxx(const Xxxxx &rhs);)
: 當
: Yyyyy y;
: Xxxxx x = y; //這時候 Xxxxx(const Yyyyy &rhs)會被呼叫
只有型態完全相同的, 才會被視為 Copy Constructor.
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.123.20.125
> -------------------------------------------------------------------------- <
作者: khoguan (Khoguan Phuann) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Wed Jun 22 23:23:32 2005
※ 引述《WanCW (笨狐狸)》之銘言:
: ※ 引述《myselves (...)》之銘言:
: : 而copy constructor的型態未必要跟class本身一樣
: : 例如 Xxxxx(const Yyyyy &rhs); 是可以的(通常都是Xxxxx(const Xxxxx &rhs);)
: : 當
: : Yyyyy y;
: : Xxxxx x = y; //這時候 Xxxxx(const Yyyyy &rhs)會被呼叫
: 只有型態完全相同的, 才會被視為 Copy Constructor.
Y y1;
X x1 = y1;
這種寫法,在「語意」上,是以 y1 為引數,呼叫 X(const Y&)
以產生一個 X 的暫時物件,然後再以這個 X 的暫時物件做引數,
呼叫 X(const X&) 來建構 x1 這個 X 的物件。「語意」上是如此,
但在compiler實作上,C++ 標準容許其做最佳化,呼叫 X(const Y&)
時,就直接建構出 x1, 而不是執行 X(const Y&) 只產生過渡性的
暫時物件,接著再呼叫 X(const X&) 才終於建構出 x1。由於許多
編譯器都有做這種最佳化,因此很容易讓人誤以為只需要有 X(const Y&)
就能寫 X x1 = y1;
Anyway,編譯器仍然得要求程式符合需要兩層建構子的「語意」限制,
也就是說,即使是做這種最佳化的編譯器,仍然得先檢查 X(const X&)
這個建構子是不是能夠被存取以執行,否則,就不能通過編譯。例如:
class Y {};
class X {
public:
X() { cout << "X()\n"; }
X(const Y&) { cout << "X(const Y&)\n"; }
X(const X&) { cout << "X(const X&)\n"; }
};
int main()
{
Y y1;
X x1 = y1;
}
上述可以通過編譯,並正確執行( <iostream>等等請自己加:)。但是
若動個手腳,將 X(const X&)移到 private: 區,那就不行通過編譯啦。
class Y {};
class X {
public:
X() { cout << "X()\n"; }
X(const Y&) { cout << "X(const Y&)\n"; }
private:
X(const X&) { cout << "X(const X&)\n"; }
};
int main()
{
Y y1;
X x1 = y1;
}
Comeau compiler 的錯誤訊息說得很清楚:
error: "X::X(const X &)" is inaccessible
(Even though the copy was eliminated, the standard
still requires it to be accessible)
X x1 = y1;
^
這樣就可看出 X(const X&) 對於 X x1 = y1; 這個敘述的必要性了。
當然,若根本不宣告 X(const X&) 的話,compiler 依標準會默默地
(implicitly)幫我們生出一個來,那當然還是可以編譯執行的。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
> -------------------------------------------------------------------------- <
作者: UNARYvvv (有趣生活) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Wed Jun 22 23:58:39 2005
※ 引述《khoguan (Khoguan Phuann)》之銘言:
: ※ 引述《WanCW (笨狐狸)》之銘言:
: : 只有型態完全相同的, 才會被視為 Copy Constructor.
: Y y1;
: X x1 = y1;
: 這種寫法,在「語意」上,是以 y1 為引數,呼叫 X(const Y&)
: 以產生一個 X 的暫時物件,然後再以這個 X 的暫時物件做引數,
: 呼叫 X(const X&) 來建構 x1 這個 X 的物件。「語意」上是如此,
: 而 compiler 實作上,C++ 標準容許其做最佳化,直接呼叫 X(const Y&)
: 來建構 x1, 而不用第一步執行 X(const Y&) 以產生過渡性的暫時
: 物件。
想請問一下最後三行
是直接呼叫 X(const Y&) 沒錯,畢竟傳入引數就是一個 Y
但那句「而不用第一步執行 X(const Y&) .....(略)」
有點看不太懂了
為其他型別定義不同 constructor 還蠻有用的
有時候還會定義一組提供互轉的行為
例如若有某個 Integer class
那它能夠以一個 int 初始化也蠻合理的
要能讓 Integer class 被轉成 int 應該也是可以提供的功能
class X{
int _val;
public:
X(int i=0) : _val(i) {}
operator int() const { return _val; }
};
void show(int i){
cout<<i<<endl;
}
int main(){
X x1 = 123;
show(x1);
return 0;
}
然後有時候反而要刻意要避免編譯器自動進行轉換
又得在 constructor 前加上 explicit ...
的確 C++ 太多東西了
不過很多東西還真的蠻有趣的~
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.59.30.19
※ 編輯: UNARYvvv 來自: 61.59.30.19 (06/23 00:17)
> -------------------------------------------------------------------------- <
作者: cplusplus (永夜) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Thu Jun 23 00:13:27 2005
※ 引述《UNARYvvv (有趣生活)》之銘言:
: ※ 引述《khoguan (Khoguan Phuann)》之銘言:
: : Y y1;
: : X x1 = y1;
: : 這種寫法,在「語意」上,是以 y1 為引數,呼叫 X(const Y&)
: : 以產生一個 X 的暫時物件,然後再以這個 X 的暫時物件做引數,
: : 呼叫 X(const X&) 來建構 x1 這個 X 的物件。「語意」上是如此,
: : 而 compiler 實作上,C++ 標準容許其做最佳化,直接呼叫 X(const Y&)
: : 來建構 x1, 而不用第一步執行 X(const Y&) 以產生過渡性的暫時
: : 物件。
: 想請問一下最後三行
: 是直接呼叫 X(const Y&) 沒錯,畢竟傳入引數就是一個 Y
: 但那句「而不用第一步執行 X(const Y&) .....(略)」
: 有點看不太懂了
X x=y; => X x=X(y); 語意上本來該是這樣
C++ ISO定義為直接...
X x(y); 這樣
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.115.205.46
> -------------------------------------------------------------------------- <
作者: UNARYvvv (有趣生活) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Thu Jun 23 00:29:18 2005
※ 引述《cplusplus (永夜)》之銘言:
: ※ 引述《UNARYvvv (有趣生活)》之銘言:
: : 想請問一下最後三行
: : 是直接呼叫 X(const Y&) 沒錯,畢竟傳入引數就是一個 Y
: : 但那句「而不用第一步執行 X(const Y&) .....(略)」
: : 有點看不太懂了
: X x=y; => X x=X(y); 語意上本來該是這樣
: C++ ISO定義為直接...
: X x(y); 這樣
嗯 我懂你的意思 謝了~
關於這個我一向是把 X x(y); X x=X(y); X x=y; 三者當作等義
( 記得以前看 C++ Primer 作者還特別釐清
X x=y; 到底是執行 operator= 還是 copy constructor )
不過 X x=y; 也只限單一參數的 constructor 能這樣用了
個人平時為了統一 constructor 的寫法,倒是只會寫 X x(y); 的初始形式..
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.59.30.19
※ 編輯: UNARYvvv 來自: 61.59.30.19 (06/23 00:51)
> -------------------------------------------------------------------------- <
作者: khoguan (Khoguan Phuann) 看板: C_and_CPP
標題: Re: [問題] default constructor
時間: Thu Jun 23 00:48:57 2005
※ 引述《cplusplus (永夜)》之銘言:
: ※ 引述《UNARYvvv (有趣生活)》之銘言:
: : 想請問一下最後三行
: : 是直接呼叫 X(const Y&) 沒錯,畢竟傳入引數就是一個 Y
: : 但那句「而不用第一步執行 X(const Y&) .....(略)」
: : 有點看不太懂了
: X x=y; => X x=X(y); 語意上本來該是這樣
可以這樣理解,但是若真的寫成 X x = X(y); 就是明示地(explicitly)
用 y 建構出一個 X 的暫時物件,和 X x = y; 那個 y 用隱含的(implicit)
方式建構出一個 X 的暫時物件不完全一樣。
: C++ ISO定義為直接...
: X x(y); 這樣
X x=y; 和
X x(y); 兩者是不同的。
前者的語意要兩層的 ctor, 後者只是一層 ctor.
前者遇到 explict X(const Y&); 就編譯不過,後者可以。
這個 explict 就是上述 explicit 和 implicit 不完全一
樣的地方。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.130.208.168
... <看更多>