【问题标题】:Erroneous/Incorrect C2248 error using Visual Studio 2010使用 Visual Studio 2010 的错误/不正确 C2248 错误
【发布时间】:2010-05-18 16:14:00
【问题描述】:

我在使用 Visual Studio 2010 编译器时发现我认为是错误/不正确的编译器错误。我正在从 Visual Studio 2005 升级我们的代码库,我遇到了一个以前正确构建但现在生成 C2248 编译器错误的构造。

显然,下面的代码 sn-p 已被通用化,但它是该场景的可编译示例。 ObjectPtr<T> C++ 模板来自我们的代码库,是相关错误的来源。似乎正在发生的事情是编译器正在生成对 ObjectPtr<T> 的复制构造函数的调用,而它不应该调用(请参阅下面SomeContainer::Foo() 方法中的我的注释块)。对于此代码构造,ObjectPtr<SomeUsefulData> 上的 SomeUsefulData * 有一个公共转换运算符,但如果 ?: 运算符,则不会在 true 表达式中选择它。相反,我在下面的块引用中得到了两个错误。

根据我对 C++ 的了解,这段代码应该可以编译。有没有其他人看到过这种行为?如果没有,有人可以指出编译器解析规则的说明,以解释为什么在这种情况下它试图生成对象的副本?

提前致谢,
迪伦·布尔克

Visual Studio 构建输出:

c:\projects\objectptrtest\objectptrtest.cpp(177):错误 C2248:“ObjectPtr::ObjectPtr”:无法访问在“ObjectPtr”类中声明的私有成员

[ T=一些有用的数据 ]
c:\projects\objectptrtest\objectptrtest.cpp(25) : 参见“ObjectPtr::ObjectPtr”的声明

[ T=一些有用的数据 ]
c:\projects\objectptrtest\objectptrtest.cpp(177):错误 C2248:“ObjectPtr::ObjectPtr”:无法访问在“ObjectPtr”类中声明的私有成员

[ T=一些有用的数据 ]
c:\projects\objectptrtest\objectptrtest.cpp(25) : 参见“ObjectPtr::ObjectPtr”的声明

[T=一些有用的数据]


下面是一个最小的、可编译的场景示例:

#include <stdio.h>
#include <tchar.h>
template<class T>
class ObjectPtr {
public:
   ObjectPtr<T> (T* pObj = NULL, bool bShared = false) :
      m_pObject(pObj), m_bObjectShared(bShared)
   {}
   ~ObjectPtr<T> ()
   {
      Detach();
   }
private:
   // private, unimplemented copy constructor and assignment operator
   // to guarantee that ObjectPtr<T> objects are not copied
   ObjectPtr<T> (const ObjectPtr<T>&);
   ObjectPtr<T>& operator = (const ObjectPtr<T>&);
public:
   T * GetObject ()
      { return m_pObject; }
   const T * GetObject () const
      { return m_pObject; }
   bool HasObject () const
      { return (GetObject()!=NULL); }
   bool IsObjectShared () const
      { return m_bObjectShared; }
   void ObjectShared (bool bShared)
      { m_bObjectShared = bShared; }
   bool IsNull () const
      { return !HasObject(); }
   void Attach (T* pObj, bool bShared = false)
   {
      Detach();
      if (pObj != NULL) {
         m_pObject = pObj;
         m_bObjectShared = bShared;
      }
   }
   void Detach (T** ppObject = NULL)
   {
      if (ppObject != NULL) {
         *ppObject = m_pObject;
         m_pObject = NULL;
         m_bObjectShared = false;
      }
      else {
         if (HasObject()) {
            if (!IsObjectShared())
               delete m_pObject;
            m_pObject = NULL;
            m_bObjectShared = false;
         }
      }
   }
   void Detach (bool bDeleteIfNotShared)
   {
      if (HasObject()) {
         if (bDeleteIfNotShared && !IsObjectShared())
            delete m_pObject;
         m_pObject = NULL;
         m_bObjectShared = false;
      }
   }
   bool IsEqualTo (const T * pOther) const
      { return (GetObject() == pOther); }
public:
   T * operator -> ()
      { ASSERT(HasObject()); return m_pObject; }
   const T * operator -> () const
      { ASSERT(HasObject()); return m_pObject; }
   T & operator * ()
      { ASSERT(HasObject()); return *m_pObject; }
   const T & operator * () const
      {  ASSERT(HasObject()); return (const C &)(*m_pObject); }
   operator T * ()
      { return m_pObject; }
   operator const T * () const
      { return m_pObject; }
   operator bool() const
      { return (m_pObject!=NULL); }
   ObjectPtr<T>& operator = (T * pObj)
      { Attach(pObj, false); return *this; }
   bool operator == (const T * pOther) const
      { return IsEqualTo(pOther); }
   bool operator == (T * pOther) const
      { return IsEqualTo(pOther); }
   bool operator != (const T * pOther) const
      { return !IsEqualTo(pOther); }
   bool operator != (T * pOther) const
      { return !IsEqualTo(pOther); }
   bool operator == (const ObjectPtr<T>& other) const
      { return IsEqualTo(other.GetObject()); }
   bool operator != (const ObjectPtr<T>& other) const
      { return !IsEqualTo(other.GetObject()); }
   bool operator == (int pv) const
      { return (pv==NULL)? IsNull() : (LPVOID(m_pObject)==LPVOID(pv)); }
   bool operator != (int pv) const
      { return !(*this == pv); }
private:
   T * m_pObject;
   bool m_bObjectShared;
};

// Some concrete type that holds useful data
class SomeUsefulData {
public:
   SomeUsefulData () {}
   ~SomeUsefulData () {}
};

// Some concrete type that holds a heap-allocated instance of
// SomeUsefulData
class SomeContainer {
public:
   SomeContainer (SomeUsefulData* pUsefulData)
   {
      m_pData = pUsefulData;
   }
   ~SomeContainer ()
   {
      // nothing to do here
   }
public:
   bool EvaluateSomeCondition ()
   {
      // fake condition check to give us an expression
      // to use in ?: operator below
      return true;
   }
   SomeUsefulData* Foo ()
   {
      // this usage of the ?: operator generates a C2248
      // error b/c it's attempting to call the copy
      // constructor on ObjectPtr<T>
      return EvaluateSomeCondition() ? m_pData : NULL;
      /**********[ DISCUSSION ]**********
      The following equivalent constructs compile
      w/out error and behave correctly:

      (1) explicit cast to SomeUsefulData* as a comiler hint
      return EvaluateSomeCondition() ? (SomeUsefulData *)m_pData : NULL;

      (2) if/else instead of ?:
      if (EvaluateSomeCondition())
         return m_pData;
      else
         return NULL;

      (3) skip the condition check and return m_pData as a
          SomeUsefulData* directly
      return m_pData;
      **********[ END DISCUSSION ]**********/
   }
private:
   ObjectPtr<SomeUsefulData> m_pData;
};

int _tmain(int argc, _TCHAR* argv[])
{
   return 0;
}

【问题讨论】:

标签: c++ visual-studio-2010 compiler-errors


【解决方案1】:

构造函数和析构函数不应该有类的模板参数:

   ObjectPtr(T* pObj = NULL, bool bShared = false) :
      m_pObject(pObj), m_bObjectShared(bShared)
   {}

(注意缺少&lt;T&gt;

但我认为这无关紧要。请参阅下面的答案...

【讨论】:

    【解决方案2】:

    我不拥有 C++ 标准的实际副本,但从 this draft,第 102-103 页,如果 expression ? E1 : E2,类型为 T1 和 T2,并且如果 T1 和T2没有继承关系,一个是右值,那么,

    使用这个过程,确定 第二个操作数是否可以 转换为匹配第三个操作数, 第三个操作数是否可以 转换为匹配第二个操作数。 如果两者都可以转换,或者一个可以 被转换,但转换是 模棱两可,程序格式不正确。 如果两者都不能转换,则 操作数保持不变并且 进一步检查被执行为 如下面所描述的。如果恰好一个 转换是可能的,即 转换应用于所选 操作数和转换后的操作数是 用于代替原始操作数 本节的其余部分。

    这似乎表明您的陈述格式不正确(因为您有 ObjectPtroperator T* 的非显式构造函数),但正如我所说,我没有实际标准。

    【讨论】:

    • 我一直认为(我现在看到的错误)声明 condition ? E1 : E2 在语义上与 if (condition) { E1 } else { E2 } 相同。我不知道E1E2 之间的类型匹配。谢谢(你的)信息。我已经通过重构代码解决了编译器错误,但是知道正确的方法仍然很好。
    猜你喜欢
    • 2018-11-06
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多