无法访问模板中的受保护成员 [英] Cannot access protected member in template

查看:75
本文介绍了无法访问模板中的受保护成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

VS 2012在以下从完整项目中剥离的最小代码中给出了'错误C2248:...无法访问在类中声明的受保护成员...'。 VS 2008没有任何问题,并按预期执行。



问题之前的行调用有问题的受保护成员,并且没有给出错误,因为它应该。模板的构造是出现问题的时候。



VS 2012 gives an 'error C2248: ... cannot access protected member declared in class...' in the following minimal code stripped from a complete project. VS 2008 has no problems with it, and executes as expected.

The line right before the issue calls the protected member in question, and no errors are given, as it should be. The template's construction is when the problem appears.

class DwlWinObject {
   };

class DwlDelegate {
   public:
      int junk;
      template <class T, void (T::*Method)(DwlWinObject*)>
      static DwlDelegate create(T* object_ptr, DwlWinObject * arg) {
         DwlDelegate d;
         d.junk = 12;
         return d;
         }
   };
   
class ModalBaseWindow : public DwlWinObject {
   protected:
      int a;
      void accept(DwlWinObject*) {
         a=0;
         }
   };

class MyModalWindow : public ModalBaseWindow {
   public:
      MyModalWindow() {
         accept(this);  //2008: No problem accessing 'accept'
         //But VS2012 gives C2248 compile error on the next line.
         //C2248 is 'cannot access protected member'
         //VS2008 has no problems with it, and executes as expected.
         DwlDelegate d = DwlDelegate::create<ModalBaseWindow,
                     &ModalBaseWindow::accept>(this, this);
         int test = d.junk;
         d.junk = 15;
         }
   };

void main() {
   MyModalWindow win;
   }





这是Visual Studio 2012中的错误,还是标准中的某些内容发生了变化?因为我真的不想让接受例程公开,所以我最好选择创建一个 accept 函数调用 ModalBaseWindow :: accept MyModalWindow 类?在完整的应用程序中,为所有曾经工作的东西所涉及的所有子类都有很多额外的代码。



谢谢,

David



Is this a bug in Visual Studio 2012, or did something in the standards change? As I don't really want to make the accept routine public, is my best option to create an accept function in the MyModalWindow class which calls the ModalBaseWindow::accept? In the full application that's a lot of additional code for all of the subclasses involved for something which once worked.

Thanks,
David

推荐答案

规则确实发生了变化,但我不认为这是问题所在。我认为这只是微软开始应用现有的。

这是一个棘手的案例,但我认为问题可以概括为试图使用受保护的成员函数指针作为模板参数来执行无法访问该成员。

解决此问题的两种方法是为创建函数提供所需的访问权限或取消保护访问功能绝对是最后的选择。



我能看到最简单的方法来给出创建函数访问而不会对代码产生更大的影响,使代表成为的朋友ModalBaseWindow



The rules did change but I don't think that's the problem. I think it's just that Microsoft started applying the existing ones.
It's a tricky case but I think the problem can be summarized as trying to use a protected member function pointer as a template parameter to a function that does not have access to that member.
The two ways to solve this are to give the create function the access it needs or to unprotect the access function which is definitely the last resort.

The easiest way I can see to give the create function access without wider impact on the code is to make the delegate a friend of ModalBaseWindow

class ModalBaseWindow : public DwlWinObject {

   friend class DwlDelegate;

   protected:
      int a;
      void accept(DwlWinObject*) {
         a=0;
         }
   };





这个问题是模板成员朋友规则是关于外部限制的C ++规范甚至更可能在MSVC编译器中被打破,而不是你已经拥有的。无论如何,试试看,让我知道。



The problem with this is that template member friend rules are about the outer limits of the C++ spec and are even more likely to be broken in the MSVC compiler than what you already have. Anyway, give it a try and let me know.


不幸的是我手头没有VS2012,但是当我想检查一段代码时,我有一个g ++一直是我的朋友遵循标准与否。使用我的VS2010和g ++ 4.5(cygwin)我已经整理了以下示例程序,可以为您提供一些有用的信息:



Unfortunately I have no VS2012 at hand but I have a g++ that has always been my friend when I wanted to check whether a piece of code follows the standard or not. Using my VS2010 and g++4.5 (cygwin) I have put together the following example program that may serve you with some useful info:

class DwlWinObject {};

class Delegate
{
public:
    virtual void Call(DwlWinObject* param) = 0;

    template <typename T>
    static Delegate* Create(T* const obj, void (T::*method)(DwlWinObject*));
};

template <typename T>
class TDelegate : public Delegate
{
public:
    virtual void Call(DwlWinObject* param)
    {
        (m_Obj->*m_Method)(param);
    }
    TDelegate(T* obj, void (T::*method)(DwlWinObject*))
    {
        m_Obj = obj;
        m_Method = method;
    }
private:
    T* m_Obj;
    void (T::*m_Method)(DwlWinObject*);
};

template <typename T>
Delegate* Delegate::Create(T* const obj, void (T::*method)(DwlWinObject*))
{
    return new TDelegate<T>(obj, method);
}

class ModalBaseWindow : public DwlWinObject
{
protected:
    void accept(DwlWinObject* param)
    {
        printf("%s(%p)\n", __FUNCTION__, param);
    }
};

class MyModalWindow : public ModalBaseWindow
{
public:
    MyModalWindow()
    {
        //accept(this);  //2008: No problem accessing 'accept'

        // compiles
        void (MyModalWindow::*Method)(DwlWinObject*) = &MyModalWindow::accept;

        // x.cpp: In constructor ‘MyModalWindow::MyModalWindow()’:
        // x.cpp:39:7: error: ‘void ModalBaseWindow::accept(DwlWinObject*)’ is protected
        // x.cpp:54:70: error: within this context
        //void (ModalBaseWindow::*Method)(DwlWinObject*) = &ModalBaseWindow::accept;

        // compiles
        Delegate* d = new TDelegate<MyModalWindow>(this, &MyModalWindow::accept);

        // x.cpp: In constructor ‘MyModalWindow::MyModalWindow()’:
        // x.cpp:39:7: error: ‘void ModalBaseWindow::accept(DwlWinObject*)’ is protected
        // x.cpp:59:72: error: within this context
        //Delegate* d = new TDelegate<ModalBaseWindow>(this, &ModalBaseWindow::accept);

        // compiles
        //Delegate* d = Delegate::Create<MyModalWindow>(this, &MyModalWindow::accept);

        // compiles
        //Delegate* d = Delegate::Create<ModalBaseWindow>(this, &MyModalWindow::accept);

        // x.cpp: In constructor ‘MyModalWindow::MyModalWindow()’:
        // x.cpp:46:7: error: ‘void ModalBaseWindow::accept(DwlWinObject*)’ is protected
        // x.cpp:81:75: error: within this context
        //Delegate* d = Delegate::Create<ModalBaseWindow>(this, &ModalBaseWindow::accept);

        // firing an event using the delegate
        d->Call(this);
    }
};

int main() {
    MyModalWindow win;
    return 0;
}





对我而言,结论是代替& ModalBaseWindow :: accept 指定方法指针时,应尝试使用& MyModalWindow :: accept



To me the conclusion is that instead of &ModalBaseWindow::accept you should try using &MyModalWindow::accept when you specify the method pointer.


这篇关于无法访问模板中的受保护成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆