ข้อกำหนดภาษาอนุญาตให้นำไปใช้งานได้<cmath>
โดยการประกาศ (และกำหนด) ฟังก์ชันมาตรฐานในเนมสเปซส่วนกลางจากนั้นนำเข้าสู่เนมสเปซstd
โดยใช้การประกาศ ไม่มีการระบุว่าใช้แนวทางนี้หรือไม่
20.5.1.2 ส่วนหัว
4 [ ... ] ในห้องสมุดมาตรฐาน c ++ อย่างไรก็ตามการประกาศ (ยกเว้นสำหรับชื่อซึ่งจะถูกกำหนดเป็นแมโครใน C) อยู่ในขอบเขต namespace (6.3.6) ของการ std
namespace ไม่มีการระบุว่าชื่อเหล่านี้ (รวมถึงการโอเวอร์โหลดใด ๆ ที่เพิ่มในข้อ 21 ถึง 33 และภาคผนวก D) ถูกประกาศครั้งแรกภายในขอบเขตเนมสเปซส่วนกลางจากนั้นจะถูกฉีดเข้าไปในเนมสเปซstd
โดยใช้การประกาศอย่างชัดเจน (10.3.3)
เห็นได้ชัดว่าคุณกำลังเผชิญกับการใช้งานอย่างใดอย่างหนึ่งที่ตัดสินใจทำตามแนวทางนี้ (เช่น GCC) คือการดำเนินงานของคุณมี::abs
ในขณะที่std::abs
เพียงแค่ "หมายถึง" ::abs
เพื่อ
คำถามหนึ่งที่ยังคงอยู่ในกรณีนี้คือทำไมนอกเหนือจากมาตรฐานที่::abs
คุณสามารถประกาศของคุณเอง::abs
ได้นั่นคือเหตุใดจึงไม่มีข้อผิดพลาดในการนิยามหลายข้อ ซึ่งอาจเกิดจากคุณลักษณะอื่นที่มีให้โดยการนำไปใช้งานบางอย่าง (เช่น GCC): พวกเขาประกาศฟังก์ชันมาตรฐานที่เรียกว่าสัญลักษณ์ที่อ่อนแอดังนั้นคุณจึงสามารถ "แทนที่" ด้วยคำจำกัดความของคุณเองได้
ทั้งสองปัจจัยร่วมกันสร้างผลที่คุณสังเกต: การเปลี่ยนอ่อนแอสัญลักษณ์ของยังส่งผลในการเปลี่ยน::abs
std::abs
สิ่งนี้สอดคล้องกับมาตรฐานภาษาอย่างไรเป็นเรื่องที่แตกต่างกัน ... ไม่ว่าในกรณีใดอย่าพึ่งพาพฤติกรรมนี้ - ภาษานี้ไม่รับประกัน
ใน GCC พฤติกรรมนี้สามารถทำซ้ำได้โดยใช้ตัวอย่างที่เรียบง่ายต่อไปนี้ ซอร์สไฟล์เดียว
#include <iostream>
void foo() __attribute__((weak));
void foo() { std::cout << "Hello!" << std::endl; }
ซอร์สไฟล์อื่น
#include <iostream>
void foo();
namespace N { using ::foo; }
void foo() { std::cout << "Goodbye!" << std::endl; }
int main()
{
foo();
N::foo();
}
ในกรณีนี้คุณจะสังเกตได้ว่านิยามใหม่ของ::foo
( "Goodbye!"
) ในไฟล์ต้นฉบับที่สองมีผลต่อพฤติกรรมของN::foo
. "Goodbye!"
ทั้งเรียกร้องให้ส่งออกจะ และถ้าคุณเอาความหมายของ::foo
จากแฟ้มแหล่งที่มาที่สองสายทั้งสองจะส่งถึงคำนิยาม "ต้นฉบับ" ของและเอาท์พุท::foo
"Hello!"
ได้รับอนุญาตที่ได้รับจากข้างต้น 20.5.1.2/4 <cmath>
จะมีการดำเนินการลดความซับซ้อนของ การใช้งานได้รับอนุญาตให้รวม C-style <math.h>
จากนั้นประกาศฟังก์ชันใหม่std
และเพิ่ม C ++ - การเพิ่มและปรับแต่งเฉพาะบางอย่าง หากคำอธิบายข้างต้นอธิบายกลไกภายในของปัญหาอย่างถูกต้องส่วนสำคัญจะขึ้นอยู่กับความสามารถในการเปลี่ยนสัญลักษณ์ที่อ่อนแอสำหรับฟังก์ชันเวอร์ชัน C
โปรดทราบว่าถ้าเราเพียงแค่ทั่วโลกแทนที่int
ด้วยdouble
ในโปรแกรมดังกล่าวข้างต้นรหัส (ภายใต้ GCC) จะทำงาน "ตามที่คาดไว้" - -5 5
มันจะออก สิ่งนี้เกิดขึ้นเนื่องจากไลบรารีมาตรฐาน C ไม่มีabs(double)
ฟังก์ชัน โดยการประกาศของเราเองabs(double)
เราไม่ได้แทนที่อะไร
แต่ถ้าหลังจากเปลี่ยนจากint
ด้วยdouble
เราก็เปลี่ยนจากabs
ไปfabs
เป็นพฤติกรรมแปลก ๆ ดั้งเดิมจะปรากฏขึ้นอีกครั้งในรัศมีภาพ (เอาต์พุต-5 -5
)
สิ่งนี้สอดคล้องกับคำอธิบายข้างต้น
abs
ไม่ถูกต้อง