MFC中使用自定义CObject派生类重载“=”“==”操作符 error C2248: “CObject::operator =” error C2678: 二进制“==”
2013-08-01 11:03:15
近期编程想用CList维护一个对象,来方便的实现增,删,改,查,里面要放多个元素,想实现这种,就要自己写结构体,或是类。类的话就让他派生自CObject吧,然后接下来会遇到两个问题,我在这里整理一下我在网上寻求的解决方法,文中所写是否是问题的标准解决办法,有待高手指教,我只是发此文章帮助和我一样遇到问题的人,和记录一下自己的学习历程。
接下来我要重现我遇到的问题,再接着写我找到的解决办法
首先看一下MSDN对CList的介绍
// CList is a template class that takes two template arguments.
// The first argument is type stored internally by the list, the
// second argument is the type used in the arguments for the
// CList methods.
// This code defines a list of ints.
CList<int,int> myIntList;
// This code defines a list of CStrings
CList<CString,CString&> myStringList;
// This code defines a list of MYTYPEs,
// NOTE: MYTYPE could be any struct, class or type definition
CList<MYTYPE,MYTYPE&> myTypeList;
新建一个MFC对话框应用程序,添加COnlineInfo类继承CObject,添加两个成员变量,DWORD m_dIPAdress; int m_nCount;
#pragma once
// CObjectInfo 命令目标
class CObjectInfo : public CObject
{
public:
CObjectInfo();
virtual ~CObjectInfo();
DWORD m_dIPAddress;
int m_nCount;
};
在对话框类中OnInitDialog()中添加定时器(SetTimer(1, 5000, NULL);)并响应OnTimer()。注意在dlg类的头文件包含自定义类#include “ObjectInfo.h”
void CTestDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nIDEvent == 1)
{
CList<CObjectInfo, CObjectInfo&> OnlineList;
KillTimer(1);
}
CDialogEx::OnTimer(nIDEvent);
}
接下来,错误来了,是这样提示的:
1>c:\users\panshiqu\documents\visual studio 2010\projects\test\test\objectinfo.h(12): error C2248: “CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)
1> c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\afx.h(535) : 参见“CObject::operator =”的声明
1> c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\afx.h(509) : 参见“CObject”的声明
1> 此诊断出现在编译器生成的函数“CObjectInfo &CObjectInfo::operator =(const CObjectInfo &)”中
这时应该往那个地方想呢,百度一下这个错误,哇哦,真的好多呀,下面我来说一下我的理解,先看CObject类是怎样写的
private:
CObject(const CObject& objectSrc); // no implementation
void operator=(const CObject& objectSrc); // no implementation
它竟然把 operator= 声明为 private,大家这个都应该有印象,声明为private的派生类是访问不到的,我们写的类继承自CObject这样的话,我们要用到它的时候是不是自己要给自己的类重写一个 operator= 函数呢,当然了,定义成public。
public:
void operator = (const CObjectInfo& src)
{
m_dIPAddress = src.m_dIPAddress;
m_nCount = src.m_nCount;
}
不管里面的内容怎样,有这个函数就行了,不然没有的话,怎么办,就去父类中找,找到啦,好高兴,准备要用,编译器突然发现是private声明,只能报错了,其实再深究一下,我只是用CList定义一个对象,怎么会用到 operator = 呢,其实这个问题完全可以忽略,因为就算你现在不用,当你给这个对象填值的时候早晚要用到,不要较真,程序都通了,调试一下看看。
下面我重现我遇到的第二个错误,修改OnTimer()实现这样的功能
void CTestDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nIDEvent == 1)
{
KillTimer(1);
CList<CObjectInfo, CObjectInfo&> OnlineList;
CObjectInfo clt1,clt2;
clt1.m_dIPAddress = 1;
clt1.m_nCount = 3;
clt2.m_dIPAddress = 2;
clt2.m_nCount = 3;
OnlineList.AddTail(clt1);
OnlineList.AddTail(clt2);
CObjectInfo ret;
ret.m_dIPAddress = 2;
POSITION pos = OnlineList.Find(ret);
CString str;
str.Format(_T("%d"),OnlineList.GetAt(pos).m_dIPAddress);
AfxMessageBox(str);
}
CDialogEx::OnTimer(nIDEvent);
}
这样第二个问题就出现了,错误是这样提示的
1>c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\afxtempl.h(156): error C2678: 二进制“==”: 没有找到接受“const CObjectInfo”类型的左操作数的运算符(或没有可接受的转换)
1> c:\program files\microsoft sdks\windows\v7.0a\include\guiddef.h(192): 可能是“int operator ==(const GUID &,const GUID &)”
1> c:\program files\microsoft sdks\windows\v7.0a\include\propkeydef.h(32): 或 “int operator ==(const PROPERTYKEY &,const PROPERTYKEY &)”
1> 尝试匹配参数列表“(const CObjectInfo, const CObjectInfo)”时
1> c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\afxtempl.h(1160): 参见对正在编译的函数 模板 实例化“BOOL CompareElements<TYPE,CObjectInfo>(const TYPE *,const ARG_TYPE *)”的引用
1> with
1> [
1> TYPE=CObjectInfo,
1> ARG_TYPE=CObjectInfo
1> ]
1> c:\program files\microsoft visual studio 10.0\vc\atlmfc\include\afxtempl.h(1145): 编译类 模板 成员函数“POSITION CList<TYPE,ARG_TYPE>::Find(ARG_TYPE,POSITION) const”时
1> with
1> [
1> TYPE=CObjectInfo,
1> ARG_TYPE=CObjectInfo &
1> ]
1> c:\users\panshiqu\documents\visual studio 2010\projects\test\test\testdlg.cpp(165): 参见对正在编译的类 模板 实例化“CList<TYPE,ARG_TYPE>”的引用
1> with
1> [
1> TYPE=CObjectInfo,
1> ARG_TYPE=CObjectInfo &
1> ]
好像和 operator == 有关,自己在网上找了段代码,照着样子加上去了
public:
bool operator == (const CObjectInfo& src)
{
return (m_dIPAddress == src.m_dIPAddress);// 随便返回
}
还是出错,好像错误还没有变化,那应该是加的这个函数写错了,我在网上搜的时候,看有的网友在 operator == 函数后面加了一个 const,我就尝试着加了,编译通过了,程序运行无错误。(为什么加const请看下文)
public:
bool operator == (const CObjectInfo& src) const
{
return (m_dIPAddress == src.m_dIPAddress);// 随便返回
}
这样就ok啦。其实前面我也并不是误打误撞去找关于 operator == 的,因为出第二个错的时候,你如果把, Find那句去掉,是没有错出来的,既然这样还不去看看在 Find 的时候,都用到了什么?用正确的程序去调试运行来学习是再好不过了,幸运的是,程序现在是已经正确的啦。
POSITION CList<TYPE, ARG_TYPE>::Find(ARG_TYPE searchValue, POSITION startAfter) const
{
ASSERT_VALID(this);
CNode* pNode = (CNode*) startAfter;
if (pNode == NULL)
{
pNode = m_pNodeHead; // start at head
}
else
{
ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
pNode = pNode->pNext; // start after the one specified
}
for (; pNode != NULL; pNode = pNode->pNext)
if (CompareElements<TYPE>(&pNode->data, &searchValue))
return (POSITION)pNode;
return NULL;
}
看到里面有个 CompareElements 很可疑,那就进去看看呀
BOOL AFXAPI CompareElements(const TYPE* pElement1, const ARG_TYPE* pElement2)
{
ENSURE(pElement1 != NULL && pElement2 != NULL);
ASSERT(AfxIsValidAddress(pElement1, sizeof(TYPE), FALSE));
ASSERT(AfxIsValidAddress(pElement2, sizeof(ARG_TYPE), FALSE));
return *pElement1 == *pElement2;
}
它返回的是一个 == 判断,等等!类型是什么?类型好像是我们自定义的CObjectInfo类,可是我们的类中没有重载 operator ==,调试至此结束,正确添加operator == 程序就不会报错
现在我们来说说 operator == 为什么要在后面加一个 const 来修饰呢?细心的朋友在上面的浏览中也发现了Find函数的实现中,后面也加了一个const来修饰,随后我就百度了一下,朋友这样总结说(取自:http://blog.csdn.net/zhangyulin54321/article/details/7877079)
首先像这样的声明void fun() const;必须是类的成员函数,不能是单独的类外部函数
其次,如果为类成员函数,他表示
(1)不能修改成员变量;
(2)不能调用非const函数;
(3)其他const函数可以调用它;(其他非const函数当然也可以调用它)
(4)只能从const对象(或引用指针)上调用,比如:const A a; a.f();
我想应该和第二条有关系,呵呵。
文章就整理到这里,发现问题多想,多问,多调试。希望我的文章能对大家有帮助