Call by value, address and reference exam questions

 傳值傳址與傳參考呼叫考題

  • 物件設計中,請用程式為範例,解釋過載(Overload)及覆寫(Override)兩者為何?
  • 請說明函式呼叫中,傳值呼叫(Call by Value)、傳址呼叫(Call byAddress)、傳參考呼叫(Call by Reference)三者差別為何,請舉例說明。
  • 寫出pass by value, reference, name的值
  • 設計一程序(procedure)或函式(function),此程序或函式在
  • 參數傳遞方式不同時:以值傳遞(passed by value)、以參照傳遞(passed by reference),會產生不同的效果,並說明為何會有不同
  • 高階語言函數傳遞,主要有四種方法 (a)call-by-reference (b)call-by-value (c)call-by-address (d)call-by-name,請就下列程式,利用上述四種參數傳遞方式,將結果輸出
  • 以下的 C 程式碼需要實作一個 SwapAndAdd function。SwapAndAdd()

概念

傳值呼叫:將變數值當做參數傳入函式。無副效應(side effect),即修改函式內的形式參數不會改到實際參數。
傳址呼叫(傳參數呼叫):將變數位址當做參數傳入函式。有副效應(side effect),即修改函式內的形式參數,會改到實際參數。
傳名呼叫:將變數的名稱當做參數傳入函式,取代形式參數。有副效應(side effect),即修改函式內的形式參數,會改到實際參數。

物件設計中,請用程式為範例,解釋過載(Overload)及覆寫(Override)兩者為何?

(10 分)另請說明函式呼叫中,傳值呼叫(Call by Value)、傳址呼叫(Call by

Address)、傳參考呼叫(Call by Reference)三者差別為何,請舉例說明。(15 

答案

過載(Overload)和覆寫(Override)是物件導向程式設計中的兩個不同概念,它們有不同的用途和特點。


1. **過載(Overload)**:


   過載是指在同一類別中定義多個具有相同名稱但具有不同參數列表的方法。這些方法可以具有不同的參數數量、不同的參數型別,或者兩者都不同。過載通常用於提供多種方式來處理相關任務。


   範例:


   ```java

   public class Calculator {

       public int add(int a, int b) {

           return a + b;

       }


       public double add(double a, double b) {

           return a + b;

       }

   }

   ```


   在這個例子中,`Calculator` 類別中有兩個名為 `add` 的方法,一個接受整數參數,另一個接受浮點數參數。這就是方法的過載。


2. **覆寫(Override)**:


   覆寫是指子類別重寫父類別中已經存在的方法,以提供自己的實現。覆寫通常用於實現多型,使子類別能夠為父類別的方法提供不同的行為


   範例:


   ```java

   public class Shape {

       public void draw() {

           System.out.println("Drawing a shape");

       }

   }


   public class Circle extends Shape {

       @Override

       public void draw() {

           System.out.println("Drawing a circle");

       }

   }

   ```


   在這個例子中,`Circle` 類別覆寫了 `Shape` 類別的 `draw` 方法,以提供特定於圓形的實現。


關於函式呼叫方式:


- **傳值呼叫(Call by Value)**:在這種情況下,方法的參數是原始值的副本,對參數的變更不會影響原始值

#include <stdio.h>


// 傳值呼叫

void modifyValue(int x) {

    x = 20;

}


int main() {

    int value = 10;


    // 傳遞變數的值

    modifyValue(value);


    // 未修改原始變數的值

    printf("Original value: %d\n", value);


    return 0;

}


- **傳址呼叫(Call by Address)**:在這種情況下,方法的參數是指向原始值的地址,對參數的變更會影響原始值。這種方式通常在語言中不常見。

#include <stdio.h>


// 傳址呼叫

void modifyValueByAddress(int *x) {

    *x = 20;

}


int main() {

    int value = 10;


    // 傳遞變數的地址

    modifyValueByAddress(&value);


    // 修改了原始變數的值

    printf("Modified value: %d\n", value);


    return 0;

}


- **傳參考呼叫(Call by Reference)**:在這種情況下,方法的參數是對原始值的引用,對參數的變更也會影響原始值。Java 不直接支持傳參考呼叫,而是以值傳遞方式處理參數。

下面傳參考呼叫(使用指針實現)

#include <stdio.h>


// 使用指針實現類似傳參考的效果

void modifyValueByReference(int *x) {

    *x = 20;

}


int main() {

    int value = 10;


    // 傳遞變數的地址

    modifyValueByReference(&value);


    // 修改了原始變數的值

    printf("Modified value: %d\n", value);


    return 0;

}


在Java中,所有參數傳遞都是以值的方式進行的。這意味著儘管你可以傳遞對象作為參數,但實際上是將對象的參考(reference)傳遞給方法。這意味著對對象的內容的更改在方法中是可見的,但對對象重新賦值(讓參考指向不同的對象)不會影響原始對象。


二、考慮下述用類似 C 語言的語法寫出的程式:

void swap(int a, int b) {

int temp;

temp = a;

a = b;

b = temp;}

void main() {

int value = 1, list[4] = {2, 3, 4, 5} //Array list is list[1..4]

swap(value, list[1]);

swap(list[1], list[2]);

swap(value, list[value])}

根據以下的參數傳遞(parameter passings)模式,逐一列出在程式執行完畢之後的

value 與 list 值:

Passed by value? (5 分)

Passed by reference? (5 分)

Passed by name?(5 分


答案

(一)

passed by value

將變數值當參數傳入函式中,沒有side effect,即改變參數值會不改變原來的數值

swap(value,list[1])//傳1,3  交換後a=3, b=1,原來的值不會改變

swap(list[1],list[2])//傳3,4  交換後a=4, b=3,原來的值不會改變

swap(value,list[value])//傳1,3 交換後a=3, b=1,原來的值不會改變

執行後value, list的值為

value=1

list[4]={2,3,4,5}


(二)

pass by reference

將變數位址當作參數傳入函式中,會有side effect,即改變參數值亦會更改原來的變數值

swap(value,list[1])//傳1,3  交換後a=3, b=1, value=3, list[1]=1

2345 ->

2145

 value=3

swap(list[1],list[2])//傳1,4  交換後a=4, b=1,list[1]=4,list[2]=1

2145 ->

2415

 value=3

swap(value,list[value])//傳3,5 交換後a=5, b=3,value=5, list[3]=3

2415 ->

2413

 value=5


執行後value, list的值為

value=5

list[4]={2,4,1,3}


(三)

pass by name

將變數名稱當作參數傳入函式中取代原來的參數名稱,會有side effect,即改變參數值亦會更改原來的變數值。執行結果跟call by reference一樣

swap(value,list[1])//傳1,3  交換後a=3, b=1, value=3, list[1]=1

 swap(int value,int list[1])

  int temp;

  temp=value;

  value=list[1];

  list[1]=temp;

swap(list[1],list[2])//傳1,4  交換後a=4, b=1,list[1]=4,list[2]=1

swap(value,list[value])//傳3,5 交換後a=5, b=3,value=5, list[3]=3

執行後value, list的值為

value=5

list[4]={2,4,1,3}

----

請用您熟習的語言,設計一程序(procedure)或函式(function),此程序或函式在

參數傳遞方式不同時:以值傳遞(passed by value)、以參照傳遞(passed by

reference),會產生不同的效果,並說明為何會有不同。(20 分


我的回答:

以下用c語言回答

(一)以值傳遞,將變數值當作參數傳入函式。無副效應,修改函式內的形式參數不會影響實際參數的值。

Void add(int a, int b){

  a=a+b;//a=6

}

int main(){

  int a =3;

int b=3;

 add(a,b);

//因為傳值呼叫,無論在函式add中做了什麼,都不會影響變數a,b的值。

}


(二)以參照傳遞,將變數地址當作參數傳入函式。有副效應,修改函式內的形式參數會影響實際參數的值。

Void add(int &a, int &b){

  *a=*a+*b;//a=6

}

int main(){

  int a =3;

int b=3;

 add(a,b);

//因為傳參照呼叫,故在函式add中對變數a做加法運算,會影響變數a的值。結果a=6,b=3

}


Chatgpt 的回答:

以下是使用Python語言的範例程式,展示了在不同的參數傳遞方式(值傳遞和參照傳遞)下會產生不同效果的情況。


```python

# 以值傳遞方式傳遞參數

def value_pass(x):

    x = x * 2


# 以參照傳遞方式傳遞參數

def reference_pass(lst):

    for i in range(len(lst)):

        lst[i] = lst[i] * 2


# 主程式

if __name__ == '__main__':

    a = 5

    print("原始值 (以值傳遞):", a)

    value_pass(a)

    print("值傳遞後的值:", a)


    numbers = [1, 2, 3, 4]

    print("原始列表 (以參照傳遞):", numbers)

    reference_pass(numbers)

    print("參照傳遞後的列表:", numbers)

```


這個程式示範了兩個函數:`value_pass` 和 `reference_pass`。`value_pass` 接收一個參數並以值傳遞方式處理,而 `reference_pass` 接收一個列表作為參數,以參照傳遞方式處理。


當呼叫 `value_pass` 函數時,原始變數 `a` 的值不受影響,因為它是以值傳遞方式傳遞的,對函數內的 `x` 進行操作不會影響原始值。


當呼叫 `reference_pass` 函數時,原始列表 `numbers` 的值會被修改,因為它是以參照傳遞方式傳遞的,對函數內的 `lst` 進行操作會影響原始列表。


這個範例展示了值傳遞和參照傳遞之間的差異,值傳遞時不會影響原始值,而參照傳遞時會影響原始資料。


在高階語言函數傳遞,主要有四種方法 (a)call-by-reference (b)call-by-value (c)call-by-address (d)call-by-name,請就下列程式,利用上述四種參數傳遞方式,將結果輸出。(16 分)

我的答案



(c)同(a)
(d) call by name 將變數名稱當參數傳入函式,並取代函式內的形式參數。
此時函式fun的
x被i取代
y被a取代
z被list[i]+a取代得
i=y+1;=>i=a+1;i=1+1=2
y=y+1;=>a=a+1;a=1+1=2
x=z+x;=>i=list[i]+a+i;i=list[2]+2+2=3+2+2=7
會輸出 i=7, list[i]=8


下面為chatgpt回答

int i= 0;

void fun(int x, int y, int z) {

  i=y+1;

  y=y+1;

  x=z+x;

}

main( ){

 int list[12]={1,2,3,4,5,6,7,8,9,10,11,12};

int a=1; 

fun(i, a, list[i]+a); 

printf(“i=%d, list[i]=%d”, i, list[i]);

}


以下是对于不同参数传递方式的程序输出:


(a) Call-by-reference (指针方式) 的输出:


```

i=2, list[i]=2

```


(b) Call-by-value (值传递方式) 的输出:


```

i=1, list[i]=2

```


(c) Call-by-address (指针方式) 的输出:


```

i=2, list[i]=2

```


(d) Call-by-name (文本替换方式) 的输出:


```

i=2, list[i]=3

```


请注意,在不同参数传递方式下,变量 `i` 和 `list[i]` 的值会有不同的变化。



Comments

Popular posts from this blog

How to write data into a excel file using vbscript

Format date as yyyy-mm-dd using vbscript