【问题标题】:Call a protected base class function from nested struct从嵌套结构调用受保护的基类函数
【发布时间】:2012-11-29 11:16:01
【问题描述】:

通常嵌套结构可以访问所属类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();
}

我不明白为什么在使用mpl::inherit 时,如果是protected,我不能调用baseProtectedFunc()

为什么我可以在第一个示例中调用基类受保护函数,而在第二个示例中不可以?

【问题讨论】:

  • 可能与问题有关:stackoverflow.com/questions/11933999/…。这似乎是一个 gcc 错误。
  • @JurajBlaho 感谢您的输入,我怀疑是编译器错误,但没有其他东西可以尝试代码...

标签: c++ templates boost boost-mpl


【解决方案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_;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-11
    • 2014-08-29
    • 2016-03-26
    • 2012-08-19
    • 2021-10-05
    • 2022-11-16
    • 2012-06-04
    相关资源
    最近更新 更多