Storage
Let's consider storage first. Storage is extremely expensive. It costs 20000 gas to set a storage location from zero to a value, and 5000 gas to change its value. (You do get some gas back for resetting a location to 0.) The reason is that a contract's storage values are stored on the blockchain forever which has a real-world cost. It's also 200 gas to read a word, compared with 3 for memory.
So for storage, use it only when you really must.
When must you use storage? For values that have to be persisted between different contract calls. For example the balances of accounts for an ERC20 token. Storage updates are state updates of your contract and are not really for temporary data. Storage of one contract can also be read by another contract, or by querying the blockchain without running the contract.
You can think of it like hard disk/SSD, if you like. Storage retains its value when the computer's not running.
Memory
Memory is relatively much cheaper than storage. It costs 3 gas to read or write a word, plus some gas if you are expanding memory. For a few KB it's very cheap indeed, but the cost goes up quadratically the more you use: a megabyte of memory will cost a couple of million gas.
However, the memory is only accessible during contract execution; once execution is finished, its contents are discarded.
When should you use memory? Pretty much for everything non-permanent. It's the general workhorse.
You can think of it like a computer's RAM. It vanishes when the computer is not running.
Stack
The costs of storing data on the stack are similar to those for memory. Sometimes there will be less overhead from having to push memory addresses to the stack; sometimes there will be more overhead as the compiler has to shuffle things around on the stack. The stack has a maximum capacity of 1024 items, but only the top 16 are easily accessible. If you run out of stack then contract execution will fail. The compiler generally uses it for intermediate values in computations and other scratch quantities.
On the whole, I'd leave the stack to the compiler to work out.
The stack also does not persist after contract termination.
All the info above is buried in the Yellow Paper - I've read it so you don't have to :-)
Last question first: overloading concept applies to Solidity but, as for other programming languages supporting overloading functions, i.e. C++, they are not related to each other in any way.
Functions with same name but different parameters are identified by different signatures, so they are actually different functions. If ContractA
defines doSomething()
, ContractB
defines doSomething(string myString)
, and ContractB
inherits from ContractA
, final ContractB will have two valid functions that user can call: doSomething()
and doSomething(string myString)
. Visibility also is part of the signature, but it can't be overloaded.
Main question now. From the outside of the contract, you cannot call a base function that has been overridden. This is because what you are calling from the outside is the final contract implementation, no matter how you define the interface on the client to call it.
If you defines
contract EvilDoer{
function doSomethingEvil{
A contractB = A(addressOfdeployedB);
contractB.doSomething();
}
}
You are simply defining another - and more restrictive - pointer to ContractB
and to its implementation of doSomething()
. And its implementation is the last one.
But hei, I know default function visibility is public, what if I define explicitly the base function in ContractA
as external
?
Not much, because you cannot override a function changing its extended signature. Visibility and return parameters are part of the extended function signature, so the compiler throws an error:
TypeError: Override changes extended function signature.
If you want to compile you need to use the same external
modifier also in the ContractB
function, and then again, the last implementation of function wins in any case.
Please note that changing visibility or return parameters it's not considered an overload neither, because functions are identified by signatures, contracts can't have two functions with the same signature and different extended attributes.
For more information about inheritance topics you can read the official documentation, in particular the information about the super
keyword and the final inheritance graph of the contract.
Best Answer
You can find the answer in another question: Does stack persist through external calls?
The same happens for memory.