簡體   English   中英

這是標准的C ++代碼嗎?

[英]Is this a standard C++ code?

下面簡單的一段代碼,用VC2008編譯但g ++拒絕代碼:

#include <iostream>

class myclass
{
protected:
    void print() { std::cout << "myclass::print();"; }
};

struct access : private myclass
{
    static void access_print(myclass& object)
    {
        // g++ and Comeau reject this line but not VC++
        void (myclass::*function) () = &myclass::print;

        (object.*function)();
    }
};

int main()
{
    myclass object;
    access::access_print(object);
}

(/W4)在VC中打開,但它沒有發出任何警告。

g ++ 4.4.1給出了一個錯誤:

correct.cpp: In static member function ‘static void access::access_print(myclass&)’:
correct.cpp:6: error: ‘void myclass::print()’ is protected

如果g ++是正確的,我如何訪問類的受保護成員? 有另一種方式嗎?


@Suroot你是說我不應該傳遞myclass類型的對象? 實際上並不重要,g ++給出了相同的錯誤,但VC編譯代碼時沒有任何警告。

#include <iostream>

class myclass
{
protected:
    void print() { std::cout << "myclass::print();"; }
};

struct access : private myclass
{
    static void access_print()
    {
        myclass object;
        void (myclass::*function) () = &myclass::print;

        (object.*function)();
    }
};

int main()
{
    access::access_print();
}

這是對的。 上面引用了標准的相關部分,但這是它的價值的基本原理。

C ++中protected的語義意味着“這個成員可以從這個類或任何派生類的方法訪問,但只有當被訪問的對象的動態類型保證與 *this 的類型相同或派生時 ” 。

后一點可能不太明顯,所以這是一個例子:

 class Base {
 protected:
     int X;
 };

class Derived : public Base {
   void Foo(Base* b, Derived* d) {
       this->X = 123; // okay - `this` is definitely either Derived
                      // or inherited from Derived

       d->X = 456;    // also okay, for the same reason

       b->X = 789;    // NOT OKAY; b could point to instance of some other class
                      // Derived2, which isn't inherited from Derived!
   }
};

這是設計 - 想法是Derived2可以對如何處理受保護的成員(不變量等等)有自己的看法,它應該嚴格地介於它和它的基類(及其派生類之間,但是只有當它決定不通過使隱藏的那場private )。 跨層次訪問與此模型相反,因為它實際上意味着基類預先決定整個層次結構; 對於深度層次結構之上的非常抽象的類,這可能是不合需要的。

現在回到你的具體問題 - 現在應該是相當明顯的。 獲得成員函數指針后,可以使用匹配類型的任何接收器調用該指針指向的函數。 對於基類的受保護方法,這意味着,如果你可以獲得一個指向它的指針到基類(而不是你自己的類),你可以調用它,向它傳遞一個指向不同於你的類型的指針類(或從中派生),違反了上面概述的受保護訪問規則。 因此,您不得這樣做。

我相信g ++和comeau是正確的。 受保護成員的說明符必須是“access”或派生類型,所以我相信代碼:

void (myclass::*function) () = &access::print;

會編譯。

我相信這是因為11.5.1:

...如果訪問[編輯。 對於受保護的成員]是形成指向成員的指針,嵌套名稱說明符應命名派生類(或從該類派生的任何類)。

由於object是作為參數傳遞的,因此您無法直接訪問private / protected函數。

編輯:將myclass更改為object

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM