2012-11-29 60 views
2

通常,嵌套結構可以訪問擁有類publicprotectedpublic成員函數。還有調用基類的protected成員函數從嵌套結構中,即下面的代碼編譯和工作正常沒有問題:從嵌套結構調用受保護的基類函數

#include <iostream> 

class Base 
{ 
public: 
    Base() 
    {} 

protected: 
    void baseProtectedFunc() 
    { 
     std::cout << __func__ << "Called for Base\n"; 
    } 
}; 

class Derived : public Base 
{ 
public: 
    explicit Derived() : Base() 
    {} 

    void accessBaseProtectedFuncFromNested() 
    { 
     Nested myNested(this); 
     myNested(); 
    } 

private: 
    struct Nested 
    { 
     explicit Nested(Derived* ptr) : derived_(ptr) 
     {} 

     void operator()() 
     { 
      derived_->baseProtectedFunc(); 
     } 

     Derived* derived_; 
    }; 
}; 

int main(int, char**) 
{ 
    Derived myDerived; 
    myDerived.accessBaseProtectedFuncFromNested(); 
    return 0; 
} 

現在,考慮使用mpl::inherit_linearly生成的基類下面的代碼派生,使用的類型的一個mpl::vector

#include <iostream> 
#include <typeinfo> 

#include <boost/mpl/vector.hpp> 
#include <boost/mpl/inherit.hpp> 
#include <boost/mpl/inherit_linearly.hpp> 
#include <boost/mpl/for_each.hpp> 

template<typename T> 
class Base 
{ 
public: 
    Base() 
    {} 

protected: 
    void baseProtectedFunc() 
    { 
     std::cout << __func__ << "Called for Base< " << typeid(T).name() << " >\n"; 
    } 
}; 

typedef boost::mpl::vector< long 
    , unsigned 
    , bool 
    , std::string 
    > parameter_type_list_t; 

typedef boost::mpl::inherit_linearly< parameter_type_list_t 
        , boost::mpl::inherit< boost::mpl::_1 
             , Base<boost::mpl::_2> > 
        >::type base_types; 

class Derived : public base_types 
{ 
public: 
    explicit Derived() : base_types() 
    {} 

    template<typename T> 
    void accessBaseProtectedFuncFromNested() 
    { 
     Nested myNested(this); 

     myNested.someFunc<T>(); 
    } 

private: 
    struct Nested 
    { 
     explicit Nested(Derived* ptr) : derived_(ptr) 
     {} 

     template< typename T > 
     void someFunc() 
     { 
      Base<T>* base = static_cast<Base<T>*>(derived_); 
      base->baseProtectedFunc(); 
     } 

     Derived* derived_; 
    }; 
}; 

int main(int, char**) 
{ 
    Derived myDerived; 
    myDerived.accessBaseProtectedFuncFromNested<unsigned>(); 

    return 0; 
} 

使用GCC版本4.4.6-3(在C++ 03和C++ 0X模式)被產生以下錯誤:

friend-prot.cpp: In member function ‘void Derived::Nested::someFunc() [with T = unsigned int]’: 
friend-prot.cpp:47: instantiated from ‘void Derived::accessBaseProtectedFuncFromNested() [with T = unsigned int]’ 
friend-prot.cpp:82: instantiated from here 
friend-prot.cpp:17: error: ‘void Base<T>::baseProtectedFunc() [with T = unsigned int]’ is protected 
friend-prot.cpp:72: error: within this context 

如果我編寫函數,我試圖調用public代碼編譯並按預期工作。

我可以通過添加額外的private成員函數得到解決的問題得出簡單地從嵌套調用,即轉發:

struct Nested 
{ 
    explicit Nested(Derived* ptr) : derived_(ptr) 
    {} 

    template< typename T > 
    void operator()() 
    { 
     derived_->forwarder<T>(); 
    } 

    Derived* derived_; 
}; 


template< typename T > 
void forwarder() 
{ 
    Base<T>::baseProtectedFunc(); 
} 

我不明白爲什麼我不能把baseProtectedFunc()如果是protected時使用mpl::inherit

爲什麼我可以在第一個示例中調用基類保護功能,而不是在第二個示例中調用?

+1

它可能與問題:HTTP://計算器。 com/questions/11933999/why-it-not-possible-to-use-private-method-in-a-lambda。這看起來像一個gcc的錯誤。 –

+0

@JurajBlaho感謝您的輸入,我懷疑一個編譯器錯誤,但沒有其他任何東西來嘗試代碼... – mark

回答

1

你會發現,如果你寫的轉發功能

template <typename T> 
void forwarder() 
{ 
    Base<T>* base = static_cast<Base<T>*>(derived_); 
    base->baseProtectedFunc(); 
} 

,你會得到同樣的錯誤的問題是,要轉換成基指針掩蓋編譯器的事實,baseProtectedFunc從實際訪問指定指針的當前上下文。由於這是模糊的,編譯器必須假定訪問不允許通過該指針。

由於語法您在轉發功能使用,也可從嵌套類中使用,該解決方案是非常簡單和優雅:

struct Nested 
{ 
    explicit Nested(Derived* ptr) : derived_(ptr) 
    {} 

    template< typename T > 
    void someFunc() 
    { 
     derived_->Base<T>::baseProtectedFunc(); /* <-- Changed */ 
    } 

    Derived* derived_; 
}; 
+0

謝謝,我應該嘗試... – mark

相關問題