const ก่อนพารามิเตอร์เทียบกับ const หลังชื่อฟังก์ชัน c ++


89

อะไรคือความแตกต่างระหว่างสิ่งนี้

friend Circle copy(const Circle &);

และอะไรทำนองนี้

friend Circle copy(Circle&) const;

ฉันรู้ว่า const หลังจากฟังก์ชันถูกใช้เพื่อบอกคอมไพเลอร์ว่าฟังก์ชันนี้จะไม่พยายามเปลี่ยนอ็อบเจ็กต์ที่เรียกใช้แล้วอีกอันล่ะ?


6
ที่คุณจะไม่เปลี่ยนพารามิเตอร์คืออีกอัน
ชาด

คำตอบ:


199

รูปแบบแรกหมายความว่าCircleออบเจ็กต์(สถานะของ) ที่ผูกไว้กับการอ้างอิงซึ่งเป็นพารามิเตอร์ของcopy()ฟังก์ชันจะไม่ถูกเปลี่ยนแปลงโดยcopy()ผ่านการอ้างอิงนั้น การอ้างอิงที่มีการอ้างอิงถึงconstดังนั้นมันจะเป็นไปไม่ได้ที่จะเรียกฟังก์ชั่นสมาชิกของผ่านการอ้างอิงที่ยังไม่ได้ตัวเองมีคุณสมบัติเป็นCircleconst

ในทางกลับกันรูปแบบที่สองผิดกฎหมาย: มีเพียงฟังก์ชันของสมาชิกเท่านั้นที่สามารถมีconstคุณสมบัติเหมาะสมได้ (ในขณะที่สิ่งที่คุณกำลังประกาศมีfriendฟังก์ชันส่วนกลาง)

เมื่อกำหนดconstคุณสมบัติของฟังก์ชันสมาชิกคุณสมบัติจะอ้างถึงthisอาร์กิวเมนต์โดยปริยาย กล่าวอีกนัยหนึ่งฟังก์ชันนั้นจะไม่ได้รับอนุญาตให้เปลี่ยนสถานะของวัตถุที่เรียกใช้ (วัตถุที่ชี้โดยthisตัวชี้โดยนัย) - ยกเว้นmutableวัตถุ แต่นั่นเป็นอีกเรื่องหนึ่ง

พูดด้วยรหัส:

struct X
{
    void foo() const // <== The implicit "this" pointer is const-qualified!
    {
        _x = 42; // ERROR! The "this" pointer is implicitly const
        _y = 42; // OK (_y is mutable)
    }

    void bar(X& obj) const // <== The implicit "this" pointer is const-qualified!
    {
        obj._x = 42; // OK! obj is a reference to non-const
        _x = 42; // ERROR! The "this" pointer is implicitly const
    }

    void bar(X const& obj) // <== The implicit "this" pointer is NOT const-qualified!
    {
        obj._x = 42; // ERROR! obj is a reference to const
        obj._y = 42; // OK! obj is a reference to const, but _y is mutable
        _x = 42; // OK! The "this" pointer is implicitly non-const
    }

    int _x;
    mutable int _y;
};

12
Helluva ตอบ! ขอขอบคุณ!
SexyBeast

1
ดังนั้นสำหรับกรณีที่สองถ้าฉันมีconstวัตถุobjคลาสXและฉันเรียกbar()แบบobj.bar(obj)นั้นมันควรจะเกิดอะไรขึ้นและทำไม? ไม่ควรobj._x = 42ล้มเหลวเนื่องจากobjมีการประกาศconstในผู้โทร?
SexyBeast

1
แล้วกรณีที่คุณสร้างฟังก์ชันแถบหลัง ( void bar(X const& obj) {...}) มีลักษณะเช่นนี้ล่ะ? void bar(const X& obj) {...}การย้ายconstคีย์เวิร์ดไปยังตำแหน่งนี้เปลี่ยนแปลงอะไรไหม ถ้าเป็นเช่นนั้นช่วยเพิ่มตัวอย่างนี้ด้วยได้ไหม
Gabriel Staples

1
@GabrielStaples มันเหมือนกัน constใช้กับสิ่งที่อยู่ทางซ้ายหรือกับสิ่งที่อยู่ทางขวาในกรณีที่ไม่มีอะไรอยู่ทางซ้าย ในกรณีของคุณคุณจะเห็นว่าทั้งสองรุ่นจะนำไปใช้const X
Andreas Flöjt

69

เมธอดคลาส C ++ มีthisพารามิเตอร์โดยนัยซึ่งมาก่อนค่าที่ชัดเจนทั้งหมด ดังนั้นฟังก์ชันที่ประกาศภายในคลาสดังนี้:

class C {
  void f(int x);

คุณสามารถจินตนาการได้ว่ามีลักษณะดังนี้:

  void f(C* this, int x);

ตอนนี้ถ้าคุณประกาศด้วยวิธีนี้:

  void f(int x) const;

เหมือนกับว่าคุณเขียนสิ่งนี้:

  void f(const C* this, int x);

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


2
แก้ไขได้อย่างสมบูรณ์แบบ แต่ไม่ตอบคำถามซึ่งไม่ได้หมายถึงวิธีการเรียน แต่เป็นฟังก์ชันเพื่อน
mAh

5
ใช่ฉันเลือกที่จะเพิกเฉยต่อfriendส่วนนี้เพราะฉันคิดว่ามันไม่เกี่ยวข้องกับคำถามที่แท้จริงของ OP (หรือคำถามที่แท้จริงจะกลายเป็นอะไรเมื่อปัญหาทั้งหมดปรากฏขึ้น) ไม่ว่าจะเป็น
John Zwinck

ฉันคิดว่ามันทำให้เข้าใจผิดเล็กน้อยที่จะพูดว่า "คุณสามารถเรียกใช้เมธอดบนวัตถุ const ของประเภทคลาสได้" เนื่องจากคุณสามารถเรียกใช้เมธอด const บนวัตถุ const หรือวัตถุที่ไม่ใช่ const ได้ในขณะที่ฟังก์ชันที่ไม่ใช่ const สามารถเรียกได้โดยวัตถุที่ไม่ใช่ const มิฉะนั้นนี่คือคำตอบที่ฉันชอบ
csguy

8
Circle copy(Circle&) const;

ทำให้ฟังก์ชั่นconstตัวเอง สามารถใช้ได้เฉพาะกับฟังก์ชันสมาชิกของคลาส / โครงสร้าง

การสร้างฟังก์ชันสมาชิกconstหมายความว่า

  • มันไม่สามารถเรียกใช้ฟังก์ชันไม่ใช่สมาชิก const ใด ๆ
  • มันไม่สามารถเปลี่ยนตัวแปรสมาชิกใด ๆ
  • สามารถเรียกโดยconstวัตถุ ( constวัตถุสามารถเรียกconstใช้ฟังก์ชันเท่านั้น) ออบเจ็กต์ที่ไม่ใช่องค์ประกอบสามารถเรียกใช้constฟังก์ชันได้
  • มันจะต้องเป็นสมาชิกของฟังก์ชั่นชั้น ' วง '

ลองพิจารณาสิ่งต่อไป:

Circle copy(const Circle &);

ในขณะนี้หมายความว่าไม่สามารถเปลี่ยนพารามิเตอร์ที่ส่งผ่านภายในฟังก์ชันได้ อาจเป็นหรือไม่เป็นฟังก์ชันสมาชิกของคลาสก็ได้

หมายเหตุ:เป็นไปได้ที่จะโอเวอร์โหลดฟังก์ชันในลักษณะที่มีconstฟังก์ชันเดียวกันและเวอร์ชันที่ไม่ใช่ const


8

มาล้างความสับสนทั้งหมดที่เกี่ยวข้องกับ const


constมาจากค่าคงที่ค่าเฉลี่ยบางอย่างไม่สามารถเปลี่ยนแปลงได้ แต่สามารถอ่านได้

  1. หากเราตรวจสอบตัวแปรของเราด้วยconstคำหลักเราจะไม่สามารถเปลี่ยนแปลงได้ในภายหลัง
    เช่นตัวแปร const ต้องเริ่มต้นเมื่อมีการประกาศ
    constint var =25;
    var =50; // gives error

  2. หากเรากำหนดตัวแปรตัวชี้ของเราด้วยหลังจากนั้นเราจะไม่สามารถเปลี่ยนตัวชี้ได้ แต่เนื้อหาของตัวชี้สามารถเปลี่ยนแปลงได้ เช่น // แต่const *

    int *const ptr = new int;
    ptr = new int; //gives error

    *ptr=5445; //allowed

  3. หากเราตรวจสอบคุณสมบัติตัวแปรพอยน์เตอร์ด้วยก่อนหน้านั้นเราสามารถเปลี่ยนตัวชี้ได้ แต่เนื้อหาของตัวชี้ไม่สามารถเปลี่ยนแปลงได้ เช่น // แต่const *

    intconst* ptr = new int(85);
    //or
    constint * ptr = new int(85);
    ptr = new int; // allowed

    *ptr=5445; // gives error

  4. ตัวชี้และเนื้อหาทั้งค่าคงที่
    เช่น
    intconst*constptr = new int(85);
    //or
    constint *constptr = new int(85);
    ptr = new int; // not allowed
    *ptr=5445; // not allowed


  1. Circle copy(const Circle &);
    ที่นี่ const Circle หมายถึงค่าของ Circle สามารถอ่านได้เท่านั้นหากเราพยายามเปลี่ยนค่าของฟังก์ชัน Circle inside จะทำให้เกิดข้อผิดพลาด
  2. friend Circle copy(Circle&) const;
    ฟังก์ชันประเภทนี้ไม่ใช้สำหรับตัวแปรที่ไม่ใช่สมาชิกมันถูกใช้สำหรับคลาสหรือโครงสร้าง นี่คือฟังก์ชั่นทั้งหมดที่มีคุณภาพด้วยวิธีการคำหลัก const เราไม่สามารถเปลี่ยนตัวแปรสมาชิกวัตถุ เช่น
    class A{ public :
              int  var;
              void fun1()
                    { var = 50; // allowed
                    } 
              void fun2()const
                       { var=50; //not allowed
                       }
           }; 

4

หนึ่งหมายถึงพารามิเตอร์อีกตัวหนึ่งของฟังก์ชัน

Circle copy(const Circle &);

ซึ่งหมายความว่าไม่สามารถเปลี่ยนพารามิเตอร์ที่ส่งผ่านภายในฟังก์ชันได้

Circle copy(Circle&) const;

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

อ่านจากขวาไปซ้าย

ถ้าเราเขียนฟังก์ชันแรกใหม่เป็นCircle copy(Circle const&);ซึ่งหมายถึงสิ่งเดียวกันจะเห็นได้ชัดว่าการอ่านจากขวาไปซ้ายจะมีประโยชน์ copyเป็นฟังก์ชันที่ใช้constอ้างอิงไปยังCircleวัตถุและส่งคืนCircleวัตถุโดยอ้างอิง


0

friend Circle copy(const Circle &);// หมายถึงพารามิเตอร์คงที่ของฟังก์ชัน ไม่สามารถ 'เปลี่ยนค่าที่จัดเก็บโดยพารามิเตอร์

ต้องการลบเพื่อนในตัวอย่าง Circle copy (Circle &) const; // ไม่สามารถเปลี่ยนค่า poniter นี้ที่มีชื่อว่าฟังก์ชัน Constant member


0
friend Circle copy(const Circle &);

ค่าของพารามิเตอร์จะไม่เปลี่ยนแปลงระหว่างการเรียกใช้ฟังก์ชัน

friend Circle copy(const Circle &)const ; 

ฟังก์ชันนี้เป็นตัวเข้าถึงที่ไม่เปลี่ยนแปลงค่าใด ๆ ของสมาชิกคลาส โดยทั่วไปมีฟังก์ชันประเภทต่างๆ ได้แก่ accessors และ mutators Accessor: ตรวจสอบ แต่ไม่เปลี่ยนสถานะของวัตถุ

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