1
int Add (int a, int b = 3);
int Add (int a, int b)
{
}
2
int Add (int a, int b);
int Add (int a, int b = 3)
{
}
ทั้งสองงาน; วิธีใดเป็นมาตรฐานและเพราะเหตุใด
1
int Add (int a, int b = 3);
int Add (int a, int b)
{
}
2
int Add (int a, int b);
int Add (int a, int b = 3)
{
}
ทั้งสองงาน; วิธีใดเป็นมาตรฐานและเพราะเหตุใด
คำตอบ:
หากคุณใส่การประกาศในไฟล์ส่วนหัวและคำจำกัดความใน.cpp
ไฟล์แยกต่างหากและ#include
ส่วนหัวจาก.cpp
ไฟล์อื่นคุณจะสามารถเห็นความแตกต่างได้
โดยเฉพาะสมมติว่า:
int Add(int a, int b);
int Add(int a, int b = 3) {
...
}
#include "lib.h"
int main() {
Add(4);
}
การคอมไพล์test.cpp
จะไม่เห็นการประกาศพารามิเตอร์เริ่มต้นและจะล้มเหลวด้วยข้อผิดพลาด
ด้วยเหตุนี้นิยามพารามิเตอร์ดีฟอลต์มักจะระบุไว้ในการประกาศฟังก์ชัน:
int Add(int a, int b = 3);
b
ถูกกำหนดหนึ่งครั้งสำหรับแต่ละ .cpp
ไฟล์ที่มีส่วนหัว แต่ไม่เป็นไรเพราะคุณมีการประกาศAdd
ฟังก์ชันเพียงครั้งเดียว
ใน C ++ ข้อกำหนดที่กำหนดไว้สำหรับอาร์กิวเมนต์เริ่มต้นที่เกี่ยวข้องกับตำแหน่งของพวกเขาในรายการพารามิเตอร์มีดังนี้:
ต้องระบุอาร์กิวเมนต์เริ่มต้นสำหรับพารามิเตอร์ที่กำหนดไม่เกินหนึ่งครั้ง การระบุมากกว่าหนึ่งครั้ง (แม้จะมีค่าดีฟอลต์เหมือนกัน) ถือเป็นเรื่องผิดกฎหมาย
พารามิเตอร์ที่มีอาร์กิวเมนต์ดีฟอลต์ต้องสร้างกลุ่มที่อยู่ติดกันที่ส่วนท้ายของรายการพารามิเตอร์
ตอนนี้โปรดจำไว้ว่าใน C ++ คุณได้รับอนุญาตให้ "ขยาย" ชุดของพารามิเตอร์ที่มีอาร์กิวเมนต์เริ่มต้นจากการประกาศฟังก์ชันหนึ่งไปยังฟังก์ชันถัดไปตราบเท่าที่ข้อกำหนดข้างต้นยังคงเป็นที่พอใจอย่างต่อเนื่อง
ตัวอย่างเช่นคุณสามารถประกาศฟังก์ชันโดยไม่มีอาร์กิวเมนต์เริ่มต้น
void foo(int a, int b);
ในการเรียกใช้ฟังก์ชันนั้นหลังจากการประกาศดังกล่าวคุณจะต้องระบุอาร์กิวเมนต์ทั้งสองอย่างชัดเจน
ในภายหลัง (ต่อไป) ในหน่วยการแปลเดียวกันคุณสามารถประกาศซ้ำได้อีกครั้ง แต่คราวนี้มีอาร์กิวเมนต์เริ่มต้นเดียว
void foo(int a, int b = 5);
และจากจุดนี้คุณสามารถเรียกมันด้วยอาร์กิวเมนต์ที่ชัดเจนเพียงข้อเดียว
ยิ่งไปกว่านั้นคุณสามารถประกาศอีกครั้งและเพิ่มอาร์กิวเมนต์เริ่มต้นอีกหนึ่งอาร์กิวเมนต์
void foo(int a = 1, int b);
และจากจุดนี้คุณสามารถเรียกมันโดยไม่มีข้อโต้แย้งที่ชัดเจน
ตัวอย่างเต็มอาจมีลักษณะดังนี้
void foo(int a, int b);
int main()
{
foo(2, 3);
void foo(int a, int b = 5); // redeclare
foo(8); // OK, calls `foo(8, 5)`
void foo(int a = 1, int b); // redeclare again
foo(); // OK, calls `foo(1, 5)`
}
void foo(int a, int b)
{
// ...
}
สำหรับรหัสในคำถามของคุณตัวแปรทั้งสองนั้นใช้ได้อย่างสมบูรณ์แบบ แต่มีความหมายต่างกัน ตัวแปรแรกประกาศอาร์กิวเมนต์เริ่มต้นสำหรับพารามิเตอร์ที่สองทันที ตัวแปรที่สองจะประกาศฟังก์ชันของคุณโดยไม่มีอาร์กิวเมนต์เริ่มต้นจากนั้นจึงเพิ่มหนึ่งสำหรับพารามิเตอร์ตัวที่สอง
เอฟเฟกต์สุทธิของการประกาศทั้งสองของคุณ (กล่าวคือวิธีที่โค้ดเห็นตามการประกาศครั้งที่สอง) จะเหมือนกันทุกประการ: ฟังก์ชันมีอาร์กิวเมนต์เริ่มต้นสำหรับพารามิเตอร์ที่สอง อย่างไรก็ตามหากคุณจัดการบีบรหัสระหว่างการประกาศครั้งแรกและครั้งที่สองตัวแปรทั้งสองนี้จะทำงานแตกต่างกัน ในตัวแปรที่สองฟังก์ชันไม่มีอาร์กิวเมนต์เริ่มต้นระหว่างการประกาศดังนั้นคุณจะต้องระบุอาร์กิวเมนต์ทั้งสองอย่างชัดเจน
void foo(int a = 1, int b)
ให้ทำงานได้จะต้องมีการประกาศหลังจาก void foo(int a, int b = 5)
นั้น ใช่มันจะทำงาน และไม่ใช่ไม่ใช่ข้อผิดพลาดทางไวยากรณ์ g ++ 4.5.3 จะคอมไพล์ได้อย่างดีเยี่ยม
int foo(int)
. ฉันพบว่าฉันสามารถเขียนได้int foo(int=5)
อีกครั้งโดยเว้นชื่อพารามิเตอร์ไว้ ดูเหมือนจะยังไม่มีใครพูดถึงเรื่องนี้
วิธีแรกจะเป็นวิธีที่สอง
เนื่องจากไฟล์ส่วนหัวจะแสดงว่าพารามิเตอร์เป็นทางเลือกและค่าเริ่มต้นจะเป็นเท่าใด นอกจากนี้สิ่งนี้จะช่วยให้มั่นใจได้ว่าค่าเริ่มต้นจะเหมือนกันไม่ว่าจะใช้ไฟล์. cpp ที่เกี่ยวข้องก็ตาม
ในวิธีที่สองไม่มีการรับประกันค่าเริ่มต้นสำหรับพารามิเตอร์ที่สอง ค่าเริ่มต้นอาจเปลี่ยนแปลงได้ขึ้นอยู่กับวิธีการใช้งานไฟล์. cpp ที่เกี่ยวข้อง
อาร์กิวเมนต์ดีฟอลต์ต้องระบุด้วยชื่อฟังก์ชันที่เกิดขึ้นครั้งแรกโดยทั่วไปจะอยู่ในฟังก์ชันต้นแบบ ถ้าฟังก์ชันต้นแบบถูกละเว้นเนื่องจากนิยามฟังก์ชันยังทำหน้าที่เป็นต้นแบบด้วยดังนั้นอาร์กิวเมนต์เริ่มต้นควรระบุไว้ในส่วนหัวของฟังก์ชัน
b
จะกำหนดหลาย ๆ ครั้งครั้งเดียวสำหรับแต่ละหน่วยคอมไพล์ที่มีlib.h
ใช่หรือไม่?