实参:子例程调用期间用PERFORM语句指定的参数;
形参:子例程定义期间用FORM语句定义的参数。
引用调用;值调用;值传并返回结果。
参考链接:https://www.cnblogs.com/jiangzhengjun/p/7264657.html#_Toc410466862
Form、Function中的TABLES参数,TYPE与LIKE后面只能接标准内表类型或标准内表对象,如果要使用排序内表或者哈希内表,则只能使用USING(Form)与CHANGING方式来代替。当把一个带表头的实参通过TABLES参数传递时,表头也会传递过去,如果实参不带表头或者只传递了表体(使用了[]时),系统会自动为内表参数变量创建一个局部空的表头
不管是以TABLES还是以USING(Form)非值、CHANGE非值方式传递时,都是以引用方式(即别名,不是指地址,注意与Java中的传引用区别:Java实为传值,但传递的值为地址的值,而ABAP中传递的是否为地址,则要看实参是否是通过Type ref to定义的)传递;
但如果USING值传递,则对形参数的修改不会改变实参,因为此时不是引用传递;但如果CHANGE值传递,对形参数的修改还是会改变实参,只是修改的时机在Form执行或Function执行完后,才去修改。
Form中通过引用传递时,USING与CHANGING完全一样;但CHANGING为值传递方式时,需要在Form执行完后,才去真正修改实参变量的内容,所以CHANGING传值与传引用其结果都是一样:结果都修改了实参内容,只是修改的时机不太一样而已
FORM subr [TABLES t1 [{TYPE itab_type}|{LIKE itab}|{STRUCTURE struc}]
t2 […]]
[USING { VALUE(p1)|p1 } [ { TYPE generic_type }
| { LIKE <generic_fs>|generic_para }
| { TYPE {[LINE OF] complete_type}|{REF TO type} }
| { LIKE {[LINE OF] dobj} | {REF TO dobj} }
| STRUCTURE struc]
{ VALUE(p2)|p2 } […]]
[CHANGING{ VALUE(p1)|p1 } [ { TYPE generic_type }
| { LIKE <generic_fs>|generic_para }
| { TYPE {[LINE OF] complete_type} | {REF TO type} }
| { LIKE {[LINE OF] dobj} | {REF TO dobj} }
| STRUCTURE struc]
{ VALUE(p2)|p2 } […]]
[RAISING {exc1|RESUMABLE(exc1)} {exc2|RESUMABLE(exc2)} ...].
generic_type:为通用类型
complete_type:为完全限制类型
generic_para:为另一个形式参数类型,如下面的 b 形式参数
DATA: d(10) VALUE'11'.
FIELD-SYMBOLS: <fs> LIKE d.
ASSIGN d TO <fs>.
PERFORM aa USING <fs> d d.
FORM aa USING fs like <fs> a like d b like a.
WRITE:fs,/ a , / b.
ENDFORM.
如果没有给形式参数指定类,则为ANY类型
如果TABLES与USING、CHANGING一起使用时,则一定要按照TABLES、USING、CHANGING顺序声明
值传递中的VALUE关键字只是在FORM定义时出现,在调用时PERFORM语句中无需出现,也就是说,调用时值传递和引用传递不存在语法格式差别。
例如:
PERFORM frm_ref2 USING dref ."传递的内容为地址,属于别名引用传递
FORM frm_ref2 USING p_i TYPE REF TO i ."p_i为实参dref的别名,类似C++中的引用参数传递(传递的内容为地址,并且属于别名引用传递)
ENDFORM.
DATA : i TYPE i VALUE 100.
WRITE: / 'frm_ref===='.
PERFORM frm_ref USING i .
FORM frm_ref USING p_i TYPE i ."C++中的引用参数传递:p_i为实参i的别名
ENDFORM.
WRITE: / 'frm_val===='.
i = 100.
PERFORM frm_val USING i .
WRITE: / i."100
FORM frm_val USING value(p_i)."传值:p_i为实参i的拷贝
WRITE: / p_i."100
p_i = 300."由于是传值,所以不会修改主调程序中的实参的值
ENDFORM.
TABLES:把内表传入form中,内表值可以有变化
Extras:
*&---------------------------------------------------------------------*
*& Report ZTEST_FORM_LHY
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ztest_form_lhy.
PARAMETERS: p_carr TYPE sflight-carrid.
"p_conn TYPE sflight-connid.
DATA sflight_tab TYPE STANDARD TABLE OF sflight.
PERFORM select_sflight TABLES sflight_tab
USING p_carr.
ULINE.
WRITE:'调用程序修改之后:'.
LOOP AT sflight_tab ASSIGNING FIELD-SYMBOL(<fs_flight1>).
IF <fs_flight1>-carrid = 'AA' AND <fs_flight1>-fldate = '20230706'.
WRITE:/,<fs_flight1>-carrid,<fs_flight1>-connid,<fs_flight1>-fldate,<fs_flight1>-price,<fs_flight1>-seatsmax.
ENDIF.
ENDLOOP.
FORM select_sflight TABLES flight_tab LIKE sflight_tab
USING f_carr TYPE sflight-carrid.
SELECT *
FROM sflight
WHERE carrid = @f_carr
INTO TABLE @flight_tab.
"cl_demo_output=>display( flight_tab )."只是输出工作区没有内容
WRITE:'调用程序:'.
LOOP AT flight_tab ASSIGNING FIELD-SYMBOL(<fs_flight>).
IF <fs_flight>-carrid = 'AA' AND <fs_flight>-fldate = '20230706'.
<fs_flight>-seatsmax = 1000000000.
WRITE:/,<fs_flight>-carrid,<fs_flight>-connid,<fs_flight>-fldate,<fs_flight>-price,<fs_flight>-seatsmax.
ENDIF.
ENDLOOP.
ENDFORM.
程序输出如下:
表明,传递TABLES的时候,如果对其进行修改,是会影响到实参的!!!
*&---------------------------------------------------------------------*
*& Report ZTEST_FORM_LHY
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ztest_form_lhy.
PARAMETERS: p_carr TYPE sflight-carrid.
"p_conn TYPE sflight-connid.
DATA sflight_tab TYPE STANDARD TABLE OF sflight.
*PERFORM select_sflight TABLES sflight_tab
* USING p_carr.
PERFORM select_sflight2 USING sflight_tab p_carr.
*ULINE.
*WRITE:/, '调用程序1修改之后:'.
* LOOP AT sflight_tab ASSIGNING FIELD-SYMBOL(<fs_flight1>).
* IF <fs_flight1>-carrid = 'AA' AND <fs_flight1>-fldate = '20230706'.
* WRITE:/,<fs_flight1>-carrid,<fs_flight1>-connid,<fs_flight1>-fldate,<fs_flight1>-price,<fs_flight1>-seatsmax.
* ENDIF.
*ENDLOOP.
ULINE.
WRITE:/, '调用程序2修改之后:'.
LOOP AT sflight_tab ASSIGNING FIELD-SYMBOL(<fs_flight2>).
IF <fs_flight2>-carrid = 'AA' AND <fs_flight2>-fldate = '20230706'.
WRITE:/,<fs_flight2>-carrid,<fs_flight2>-connid,<fs_flight2>-fldate,<fs_flight2>-price,<fs_flight2>-seatsmax.
ENDIF.
ENDLOOP.
FORM select_sflight TABLES flight_tab LIKE sflight_tab
USING f_carr TYPE sflight-carrid.
SELECT *
FROM sflight
WHERE carrid = @f_carr
INTO TABLE @flight_tab.
"cl_demo_output=>display( flight_tab )."只是输出工作区没有内容
WRITE:/,'调用程序1:'.
LOOP AT flight_tab ASSIGNING FIELD-SYMBOL(<fs_flight>).
IF <fs_flight>-carrid = 'AA' AND <fs_flight>-fldate = '20230706'.
<fs_flight>-seatsmax = 1000000000.
WRITE:/,<fs_flight>-carrid,<fs_flight>-connid,<fs_flight>-fldate,<fs_flight>-price,<fs_flight>-seatsmax.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form select_sflight2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> SFLIGHT_TAB
*&---------------------------------------------------------------------*
FORM select_sflight2 USING VALUE(p_sflight_tab) LIKE sflight_tab
p_carr TYPE sflight-carrid.
SELECT *
FROM sflight
WHERE carrid = @p_carr
INTO TABLE @p_sflight_tab.
"cl_demo_output=>display( flight_tab )."只是输出工作区没有内容
WRITE:/,'调用程序2:'.
LOOP AT p_sflight_tab ASSIGNING FIELD-SYMBOL(<fs_flight>).
IF <fs_flight>-carrid = 'AA' AND <fs_flight>-fldate = '20230706'.
<fs_flight>-seatsmax = 9999999.
WRITE:/,<fs_flight>-carrid,<fs_flight>-connid,<fs_flight>-fldate,<fs_flight>-price,<fs_flight>-seatsmax.
ENDIF.
ENDLOOP.
ENDFORM.
所以用using或者changing来传递表类型