Skip to the content.

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();

   我想应该和第二条有关系,呵呵。

   文章就整理到这里,发现问题多想,多问,多调试。希望我的文章能对大家有帮助