ใน C ++“ นามแฝงเนมสเปซ” คืออะไร?


คำตอบ:


186

นามแฝง namespace เป็นวิธีที่สะดวกในการอ้างอิงชื่อเนมสเปซแบบยาวด้วยชื่อที่สั้นกว่าและแตกต่างกัน

ตัวอย่างเช่นสมมติว่าคุณต้องการใช้เวกเตอร์ตัวเลขจาก uBLAS ของ Boost โดยไม่มีusing namespaceคำสั่ง การระบุเนมสเปซเต็มรูปแบบทุกครั้งที่ยุ่งยาก:

boost::numeric::ublas::vector<double> v;

แต่คุณสามารถกำหนดนามแฝงสำหรับboost::numeric::ublas- ว่าเราต้องการย่อให้เหลือเพียงublas:

namespace ublas = boost::numeric::ublas;


ublas::vector<double> v;

7
หากต้องการอธิบาย downvotes ดังนั้น SO ไม่ใช่และจะไม่เป็นหนังสือตำราเรียนภาษา C ++ ที่ดีแทน คำถามที่คุณโพสต์จะได้รับคำตอบจากหนังสือเล่มนี้ และคุณลักษณะ "" ของการตอบคำถามของคุณเองไม่ควรนำมาใช้เพื่อให้การถอดความของหนังสือดังกล่าว

24
ไม่มีการกระทำผิดกฎหมาย ... เพื่ออธิบายว่าทำไมฉันถึงทำสิ่งนี้: มันเป็นความเข้าใจของฉันจากความเห็นของโจเอลในพอดคาสต์ว่าแม้แต่คำถาม "รายการระดับต้น" ก็เป็นเกมที่ยุติธรรมบน SO และเป็นที่ยอมรับได้ที่จะถามคำถามและตอบคำถาม ตัวคุณเองถ้าเนื้อหานั้นไม่ได้อยู่ใน SO แต่อยู่ในรูปแบบที่เข้าถึงได้ แต่เห็นได้ชัดว่านี่เป็นเรื่องขมวดคิ้วใช่ไหม?
Martin B

1
มีมารยาทในการตอบคำถามของคุณเองเพื่อหลีกเลี่ยงการระคายเคือง ในกรณีนี้มันค่อนข้างชัดเจนว่ามันไม่เคยเป็นคำถามที่แท้จริง ตัวอย่างเช่นstackoverflow.com/questions/494927/…
Marc Gravell

6
@ มาร์ติ B: ฉันไม่เห็นด้วยว่านี่เป็นคำถามระดับรายการ - ในความเป็นจริงมีคำถามที่ชัดเจนมากขึ้นถามในอดีตที่ผ่านมาตอนนี้ด้วยคะแนนเสียงมากมาย ต้องบอกว่าผู้คนอาจรู้สึกว่าคุณแค่พยายามที่จะสร้างชื่อเสียงให้ตัวเอง วิธีนี้เป็นการทำเครื่องหมายคำถาม / คำตอบหนึ่งหรือทั้งสองคำว่า "community wiki" โดยส่วนตัวแล้วฉันจะไปถามคำถามกับคุณและตอบเป็นชุมชน หากคำถามนั้นมี merrit คุณจะได้รับ ROI
Richard Corden

1
ฉันคิดว่าคำถามที่สำคัญคือคำถามนั้นเป็นของจริงหรือไม่ - เป็นสิ่งที่คุณถูกถามใช่หรือไม่เป็นสิ่งที่ผู้คนต้องการทราบหรือไม่เป็นสิ่งที่ยังไม่ได้รับการถามและตอบคำถามจาก SO หรือไม่ถ้าคุณอ่าน บล็อกโพสต์เกี่ยวกับชุมชน R โพสต์และตอบคำถามที่นี่โปรดทราบว่าพวกเขาเลือกคำถาม X อันดับสูงสุดที่ชุมชนของพวกเขาเก็บไว้ถามจริง ๆดังนั้นมันจึงมีความเกี่ยวข้องในโลกแห่งความจริงการสุ่มตัวอย่างความรู้เฉพาะภาษา มีประโยชน์น้อยกว่า
jalf

7

ค่อนข้าง #define ไม่ทำงาน

namespace Mine { class MyClass { public: int i; }; }
namespace His = Mine;
namespace Yours { class Mine: public His::MyClass { void f() { i = 1; } }; }

รวบรวมดี ให้คุณหลีกเลี่ยงการชนชื่อเนมสเปซ / คลาส

namespace Nope { class Oops { public: int j; }; }
#define Hmm Nope
namespace Drat { class Nope: public Hmm::Oops { void f () { j = 1; } }; }

ในบรรทัดสุดท้าย "อืม: โอ๊ะโอ" เป็นข้อผิดพลาดในการคอมไพล์ ตัวประมวลผลล่วงหน้าเปลี่ยนเป็น Nope :: อ๊ะ แต่ Nope เป็นชื่อคลาสแล้ว


3
#define คืออะไร บางทีคำตอบของคุณอ้างถึงคำถามรุ่นก่อนหน้าใช่ไหม
einpoklum

3

เพิ่มเติมในหัวข้อนี้http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-1-of-n

ทุกอย่างเกี่ยวกับการเลือกนามแฝงสำหรับชื่อเนมสเปซ looong เช่น:

namespace SHORT = NamespaceFirst::NameSpaceNested::Meow

จากนั้นในภายหลังคุณสามารถพิมพ์

typedef SHORT::mytype

แทน

typedef NamespaceFirst::NameSpaceNested::Meow::mytype

ไวยากรณ์นี้ใช้งานได้กับเนมสเปซเท่านั้นไม่สามารถรวมคลาสได้หลังจากพิมพ์ namespace NAME =


3

โปรดทราบว่านามแฝงเนมสเปซและการใช้คำสั่งจะได้รับการแก้ไข ณ เวลารวบรวมไม่ใช่เวลาทำงาน (โดยเฉพาะอย่างยิ่งพวกเขาทั้งคู่เป็นเครื่องมือที่ใช้บอกคอมไพเลอร์ว่าจะต้องดูที่การแก้ไขชื่อหากไม่สามารถหาสัญลักษณ์เฉพาะในขอบเขตปัจจุบันหรือขอบเขตหลักใด ๆ ) ตัวอย่างเช่นสิ่งเหล่านี้จะไม่ รวบรวม:

namespace A {
    int foo;
    namespace AA {
        int bar;
    } // namespace AA
    namespace AB {
        int bar;
    } // namespace AB
} // namespace A
namespace B {
    int foo;
    namespace BA {
        int bar;
    } // namespace BA
    namespace BB {
        int bar;
    } // namespace BB
} // namespace B

bool nsChooser1, nsChooser2;
// ...

// This doesn't work.
namespace C = (nsChooser1 ? A : B);
C::foo = 3;

// Neither does this.
// (Nor would it be advisable even if it does work, as compound if-else blocks without braces are easy to inadvertently break.)
if (nsChooser1)
    if (nsChooser2)
        using namespace A::AA;
    else
        using namespace A::AB;
else
    if (nsChooser2)
        using namespace B::BA;
    else
        using namespace B::BB;

ตอนนี้จิตใจที่อยากรู้อยากเห็นอาจสังเกตเห็นว่าconstexprมีการใช้ตัวแปรในเวลารวบรวมและสงสัยว่าพวกเขาสามารถใช้ร่วมกับนามแฝงหรือคำสั่งได้หรือไม่ สำหรับความรู้ของฉันพวกเขาไม่สามารถแม้ว่าฉันจะผิดเกี่ยวกับเรื่องนี้ หากคุณต้องการทำงานกับตัวแปรที่มีชื่อเหมือนกันในเนมสเปซที่แตกต่างกันและเลือกระหว่างตัวแปรแบบไดนามิกคุณจะต้องใช้การอ้างอิงหรือพอยน์เตอร์

// Using the above namespaces...
int& foo = (nsChooser1 ? A::foo : B::foo);

int* bar;
if (nsChooser1) {
    if (nsChooser2) {
        bar = &A::AA::bar;
    } else {
        bar = &A::AB::bar;
    }
} else {
    if (nsChooser2) {
        bar = &B::BA::bar;
    } else {
        bar = &B::BB::bar;
    }
}

ประโยชน์ที่ได้รับจากข้างต้นอาจถูก จำกัด แต่ก็ควรทำตามวัตถุประสงค์

(คำขอโทษของฉันสำหรับงานพิมพ์ใด ๆ ที่ฉันอาจพลาดในข้างต้น)


0

Namespace ใช้เพื่อป้องกันความขัดแย้งของชื่อ

ตัวอย่างเช่น:

namespace foo {
    class bar {
        //define it
    };
}

namespace baz {
    class bar {
        // define it
    };
}

ตอนนี้คุณมีแถบชื่อคลาสสองชั้นที่แตกต่างอย่างสิ้นเชิงและแยกจากกันด้วยการกำหนดเนมสเปซ

"การใช้เนมสเปซ" ที่คุณแสดงคือเพื่อให้คุณไม่ต้องระบุเนมสเปซเพื่อใช้คลาสภายในเนมสเปซนั้น ie std :: string กลายเป็นสตริง

ทรัพยากรของฉัน: https://www.quora.com/What-is-namespace-in-C++-1

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.