这堂课怎么了? [英] What's wrong with this class

查看:59
本文介绍了这堂课怎么了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我写了一个小课程来列举智能手机上的可用网络:


class CNetwork

{

public:

CNetwork(){};

CNetwork(CString& netName,GUID netguid):

_netname(netName),_ netguid(netguid){}

~CNetwork(){}

CString& getName(){return _netname; }

GUID getGuid(){return _netguid; }


私人:

CString _netname;

GUID _netguid;

};

类CNetworkList

{

public:

typedef std :: list< CNetwork *> :: iterator NetworkListIt;


CNetworkList(){}


~CNetworkList()

{

清除();

}


CNetworkList :: CNetworkList(const CNetworkList& rhs){

CopyObj(rhs);

}


CNetworkList& CNetworkList :: operator =(const CNetworkList& rhs)

{

CopyObj(rhs);

return * this;

}


void CopyObj(const CNetworkList& rhs)

{

_netlist = rhs._netlist;

}


void清除()

{

for_each(_netlist.begin(),_ netlist.end (),DeletePointer());

}


void Add(CNetwork * network)

{

_netlist.push_back(网络);

}


const CNetwork * getNetwork(CString netNameOrGuid)

{

if((netNameOrGuid.GetAt(0)==''{'')&&

netNameOrGuid.GetLength()== 39)

$

CLSID guid;

如果

(SUCCEEDED(CLSIDFromString(netNameOrGuid.GetBuffer(),& guid))) />
返回getNetwork(guid);

}

else

{

NetworkListIt it;

for(it = _netlist.begin(); it!= _netlist.end(); ++ it)

if(!(* it) - > getName()。CompareNoCase(netNameOrGuid))

return(* it);

}

返回NULL;

}


const CNetwork * getNetwork(CLSID guid)

{

if (!_netlist.empty())

清除();


NetworkListIt it;

for(it = _netlist.begin (); it!= _netlist.end(); ++ it)

if((* it) - > getGuid()== guid)

return(* it);


返回NULL;

}


private:

std :: list< CNetwork * _netlist;

};


CNetworkList getNetworkList()

{

int i = 0;

HRESULT hResult;

CNetworkList netList;


while(ConnMgrEnumDestinations(i,& connInfo)== 0)

{

CNetwork * pNetWork = new

CNetwork(CString(connInfo.szDescription),connInfo.guid);

if(pNetWork)

{

netList.Add(pNetWork);

}


i ++;

}

}


当我拨打此代码时:

m_NetworkList = getNetworkList();

我在Cstring析构函数中得到了一个断言,所以我想我的班级正在做

错误...

当我一步一步地调试时我不会''真的了解这些电话,它好像是b $ b似乎是Clear()为什么叫它dn''t


解决方案

John Doe写道:





我写了一个小课程来列举智能手机上的可用网络:


class CNetwork



为什么你需要名字前面的C?我能理解''SP''

(适用于智能手机),但是''C''?


{

public:

CNetwork(){};

CNetwork(CString& netName,GUID netguid):

_netname(netName), _netguid(netguid){}



如果你的班级拥有会员''_netname''(可能应该这样,因为

你设计的it),考虑将初始化者作为参考传递给const:


CNetwork(CString const& netName,GUID ...


>

~CNetwork(){}

CString& getName(){return _netname;}



这是一个坏主意。你正在将你班级的内部暴露给你无法控制的任何
变化甚至如果你的''网络''

需要报告它的名字,这个成员必须是''const''并且应该

返回对const的引用:


CString const& getName()cosnt {return _netname; }


GUID getGuid(){return _netguid; }



同样在这里:


GUID getGuid()const {return _netguid; }


>

private:

CString _netname;

GUID _netguid ;

};


类CNetworkList

{

public:

typedef std :: list< CNetwork *> :: iterator NetworkListIt;



这需要公开吗?


>

CNetworkList (){}


~CNetworkList()

{

清除();

}


CNetworkList :: CNetworkList(const CNetworkList& rhs){

CopyObj(rhs);

}



这是什么?为什么你不能只使用正常的复制构造函数形式:

CNetworkList :: CNetworkList(const CNetworkList& rhs):

netlist(rhs.netlist ){}


?如果它很重要,这几乎是不必要的,因为

编译器将为您提供完全相同的复制构造函数。


> ;

CNetworkList& CNetworkList :: operator =(const CNetworkList& rhs)

{

CopyObj(rhs);

return * this;

}



再一次,编译器提供的赋值运算符只能很好地工作,很可能是
。你不必自己提供。


>

void CopyObj(const CNetworkList& rhs)

{

_netlist = rhs._netlist;

}


void清除()

{

for_each(_ netlist.begin(),_ netlist.end(),DeletePointer());

}


void Add(CNetwork * network)

{

_netlist.push_back(network);

}



现在,您确实意识到您的列表是该指针的所有者

,对吧?


> ;

const CNetwork * getNetwork(CString netNameOrGuid)



如果(a)'''''这个函数的界面更好const''和(b)它的

参数没有按值传递:


const CNetwork * getNetwork(CStirng const& netNameOrGuid)const


{

if((netNameOrGuid.GetAt(0)==''{'')&&

netNameOrGuid.GetLength()== 39)

{

CLSID guid;

如果

(SUCCEEDED(CLSIDFromString(netNameOrGuid.GetBuffer(),& guid)))

返回getNetwork(guid);

}

else

{

NetworkListIt it;

for(it = _netlist.begin(); it!= _netlist.end(); ++ it)

if(!(* it) - > getName()。CompareNoCase(netNameOrGuid))

return(* it);

}

返回NULL;

}


const CNetwork * getNetwork(CLSID guid)



与上面相同的评论,


const CNetwork * getNetwork(CLSID guid)const


{

if(!_netlist.empty())

清除();


NetworkListIt it;

for(it = _netlist.begin(); it!= _netlist.end(); ++ it)

if((* it) - > getGuid()== guid)

返回(* it);


返回NULL;

}


private:

std :: list< CNetwork * _netlist;

};


CNetworkList getNetworkList()

{

int i = 0;

HRESULT hResult;

CNetworkList netList;


while(ConnMgrEnumDestinations(i,& connInfo)== 0)

{

CNetwork * pNetWork =新的
CNetwork(CString(connInfo.szDescription),connInfo.guid);

if(pNetWork)



''new''永远不会返回NULL。但是,如果发生了某些事情,你应该用
''try-catch''来包围它,因为''new''throws''s​​td :: bad_alloc''。


{

netList.Add(pNetWork);

}


i ++;

}

}


当我调用此代码时:

m_NetworkList = getNetworkList();



哪里?


我在Cstring析构函数中得到一个断言所以我想我的班级正在做

错了......

当我一步一步地调试时,我真的不理解这些电话,它好像是b $ b似乎是Clear()是叫它为什么不这样做。



发布完整代码并提供一个测试驱动程序,它将生成

网络(而不是''ConnMgrEnumDesitnations''哪个C ++没有'''有)。


V

-

请在通过电子邮件回复时删除资金''A'

我没有回复最热门的回复,请不要问


Victor Bazarov写道:


John Doe写道:



所以这里是更新代码(没有尝试新的我会在以后再做)

但现在我收到一个错误:

错误C2662:''NetworkList :: Clear'':无法转换''this''指针来自

' 'const NetworkList''''NetworkList&''


所以我已经将const添加到Clear()......

// === ========================================= //

// NetworkManager.h

// ================================ ============ //

struct DeletePointer {

template< typename T>

void operator() (const T * ptr)const

{

删除ptr;

}

};


class Network

{

public:

Network(){};

网络(CString const& netName,GUID netguid):

_netname(netName),_ netguid(netguid){}


~Network(){}

CString const& getName(){return _netname; }

GUID getGuid()const {return _netguid; }


私人:

CString _netname;

GUID _netguid;

};

类NetworkList

{

typedef std :: list< Network *> :: iterator NetworkListIt;


public:


NetworkList()

{

}


~NetworkList ()

{

清除();

}


void清除()

{

for_each(_ netlist.begin(),_ netlist.end(),DeletePointer());

}

void添加(网络*网络)

{

if(network)

_netlist.push_back(network);

}

const网络* getNetwork(CString const& netNameOrGuid)const

{

if((netNameOrGuid.GetAt( 0)==''{'')&&

netNameOrGuid.GetLength()== 39)

{

CLSID guid ;

if(SUCCEEDED(CLSIDFromString((LPOLESTR)(LPCTSTR)netN ameOrGuid,& guid)))

{

return get网络(guid);

}

}

其他

{

std :: list< Network *> :: const_iterator it;

// NetworkListIt it;

for(it = _netlist.begin(); it!= _netlist.end(); ++ it)

if(!(* it) - > getName()。CompareNoCase(netNameOrGuid))

return(* it);

}

返回NULL;

}


const网络* getNetwork(CLSID guid)const

{

if(!_netlist.empty())

清除();


std :: list< Network *> :: const_iterator it;

// NetworkListIt it;

for(it = _netlist.begin(); it!= _netlist.end(); + +它)

if((* it) - > getGuid()== guid)

return(* it);


返回NULL;

}


private:

std :: list< Network * _netlist;

};


// ============================== ============== //

// NetworkManager.cpp

// =========== ================================= //

NetworkList getNetworkList()

{

NetworkList netList;


//模拟我们从OS检索网络列表

GUID guid;

netList.Add(新网络( _T(Network1),guid));

netList.Add(新网络(_T(" Network2")),guid));


return netList;

}


// ======================= ===================== //

//测试用例

// ====== ====================================== //


void OnGettingNetworkList()

{

NetworkList netList = getNetworkList();

}


当netList被销毁时,我得到一个调试断言,因为CString

对象:


void Release()throw()

{

ATLASSERT(nRefs!= 0); <<<<< !!!!!!!!!

if(_AtlInterlockedDecrement(& nRefs)< = 0)

{

pStringMgr->免费(这);

}

}


周五, 2008年10月24日17:18:15 +0200,John Doe写道:


Victor Bazarov写道:


> John Doe写道:



所以这里是更新代码(没有尝试新的我会在以后再做)

但是现在我收到一个错误:

错误C2662:''NetworkList :: Clear'':无法将''this''指针从

''const NetworkList''转换为''NetworkList&''


所以我将const添加到Clear()......



[snip]


>

void清除()

{

for_each(_netlist.begin(),_ netlist.end(),DeletePointer());

}


在你的测试用例中调用这个函数多少次?

大概两次,对吗?

它做了什么每次?


[snip]


>

void OnGettingNetworkList()

{

NetworkList netList = getNetworkList();

}



你返回一个*复制你在函数中构建的NetworkList *。

第一个副本死掉并通过Clear()释放所有指针所以

副本包含无效指针,这是再次解除分配,

这是CString失败断言的地方,因为它已经被破坏了。
$ block $ class =post_quotes>
>

当netList被销毁时,我得到一个调试断言,因为CString

对象:


void Release ()throw()

{

ATLASSERT(nRefs!= 0); <<<<< !!!!!!!!!

if(_AtlInterlockedDecrement(& nRefs)< = 0){

pStringMgr-> Free(this );

}

}



-

OU

记得2008年6月18日,民主当天下午去世了。
http: //frapedia.se/wiki/Information_in_English


Hi,

I wrote a small class to enumerate available networks on a smartphone :

class CNetwork
{
public:
CNetwork() {};
CNetwork(CString& netName, GUID netguid):
_netname(netName), _netguid(netguid) {}

~CNetwork() {}

CString& getName() { return _netname; }
GUID getGuid() { return _netguid; }

private:
CString _netname;
GUID _netguid;
};
class CNetworkList
{
public:
typedef std::list<CNetwork*>::iterator NetworkListIt;

CNetworkList() {}

~CNetworkList()
{
Clear();
}

CNetworkList::CNetworkList(const CNetworkList& rhs) {
CopyObj(rhs);
}

CNetworkList& CNetworkList::operator=(const CNetworkList& rhs)
{
CopyObj(rhs);
return *this;
}

void CopyObj(const CNetworkList& rhs)
{
_netlist = rhs._netlist;
}

void Clear()
{
for_each( _netlist.begin(), _netlist.end(), DeletePointer ());
}

void Add(CNetwork* network)
{
_netlist.push_back(network);
}

const CNetwork* getNetwork(CString netNameOrGuid)
{
if ((netNameOrGuid.GetAt(0) == ''{'') &&
netNameOrGuid.GetLength() == 39)
{
CLSID guid;
if
(SUCCEEDED(CLSIDFromString(netNameOrGuid.GetBuffer (),&guid)))
return getNetwork(guid);
}
else
{
NetworkListIt it;
for (it = _netlist.begin(); it != _netlist.end(); ++it)
if (!(*it)->getName().CompareNoCase(netNameOrGuid))
return (*it);
}
return NULL;
}

const CNetwork* getNetwork(CLSID guid)
{
if (!_netlist.empty())
Clear();

NetworkListIt it;
for (it = _netlist.begin(); it != _netlist.end(); ++it)
if ((*it)->getGuid() == guid)
return (*it);

return NULL;
}

private:
std::list<CNetwork*_netlist;
};

CNetworkList getNetworkList()
{
int i = 0;
HRESULT hResult;
CNetworkList netList;

while( ConnMgrEnumDestinations( i, &connInfo ) == 0 )
{
CNetwork* pNetWork = new
CNetwork(CString(connInfo.szDescription), connInfo.guid);
if (pNetWork)
{
netList.Add(pNetWork);
}

i++;
}
}

When I call this code :
m_NetworkList = getNetworkList();
I got an assert in a Cstring desctructor so I suppose my class is doing
wrong...
When I debug in step by step I don''t really understand the calls, it
seems Clear() is called why it shoudn''t.


解决方案

John Doe wrote:

Hi,

I wrote a small class to enumerate available networks on a smartphone :

class CNetwork

Why do you need the ''C'' in front of the name? I can understand ''SP''
(for smartphone), but ''C''?

{
public:
CNetwork() {};
CNetwork(CString& netName, GUID netguid):
_netname(netName), _netguid(netguid) {}

If your class owns the member ''_netname'' (which it probably should, as
you designed it), consider passing the initialiser for it as a reference
to const:

CNetwork(CString const& netName, GUID...

>
~CNetwork() {}

CString& getName() { return _netname; }

This is a bad idea. You are exposing the innards of your class to any
change that you can''t control or even know about. If your ''Network''
needs to report its name, this member has to be ''const'' and should
return a reference to const:

CString const& getName() cosnt { return _netname; }

GUID getGuid() { return _netguid; }

Same here:

GUID getGuid() const { return _netguid; }

>
private:
CString _netname;
GUID _netguid;
};
class CNetworkList
{
public:
typedef std::list<CNetwork*>::iterator NetworkListIt;

Does this need to be public?

>
CNetworkList() {}

~CNetworkList()
{
Clear();
}

CNetworkList::CNetworkList(const CNetworkList& rhs) {
CopyObj(rhs);
}

What is that? Why couldn''t you just use the normal copy constructor form:

CNetworkList::CNetworkList(const CNetworkList& rhs) :
netlist(rhs.netlist) {}

? And if it matters, this is pretty much unnecessary because the
compiler will provide you with the copy constructor that does exactly that.

>
CNetworkList& CNetworkList::operator=(const CNetworkList& rhs)
{
CopyObj(rhs);
return *this;
}

Again, the assignment operator provided by the compiler will work just
fine, most likely. You don''t have to provide your own.

>
void CopyObj(const CNetworkList& rhs)
{
_netlist = rhs._netlist;
}

void Clear()
{
for_each( _netlist.begin(), _netlist.end(), DeletePointer ());
}

void Add(CNetwork* network)
{
_netlist.push_back(network);
}

Now, you do realise that your list is made the owner of that pointer
here, right?

>
const CNetwork* getNetwork(CString netNameOrGuid)

The interface of this function is better if (a) it''s ''const'' and (b) its
argument is not passed by value:

const CNetwork* getNetwork(CStirng const& netNameOrGuid) const

{
if ((netNameOrGuid.GetAt(0) == ''{'') &&
netNameOrGuid.GetLength() == 39)
{
CLSID guid;
if
(SUCCEEDED(CLSIDFromString(netNameOrGuid.GetBuffer (),&guid)))
return getNetwork(guid);
}
else
{
NetworkListIt it;
for (it = _netlist.begin(); it != _netlist.end(); ++it)
if (!(*it)->getName().CompareNoCase(netNameOrGuid))
return (*it);
}
return NULL;
}

const CNetwork* getNetwork(CLSID guid)

Same comment as above,

const CNetwork* getNetwork(CLSID guid) const

{
if (!_netlist.empty())
Clear();

NetworkListIt it;
for (it = _netlist.begin(); it != _netlist.end(); ++it)
if ((*it)->getGuid() == guid)
return (*it);

return NULL;
}

private:
std::list<CNetwork*_netlist;
};

CNetworkList getNetworkList()
{
int i = 0;
HRESULT hResult;
CNetworkList netList;

while( ConnMgrEnumDestinations( i, &connInfo ) == 0 )
{
CNetwork* pNetWork = new
CNetwork(CString(connInfo.szDescription), connInfo.guid);
if (pNetWork)

''new'' never returns NULL. You should, however, surround it with
''try-catch'' since ''new'' throws ''std::bad_alloc'' if something happens.

{
netList.Add(pNetWork);
}

i++;
}
}

When I call this code :
m_NetworkList = getNetworkList();

Where?

I got an assert in a Cstring desctructor so I suppose my class is doing
wrong...
When I debug in step by step I don''t really understand the calls, it
seems Clear() is called why it shoudn''t.

Post complete code and provide a test driver that would produce the
network (instead of ''ConnMgrEnumDesitnations'' which C++ doesn''t have).

V
--
Please remove capital ''A''s when replying by e-mail
I do not respond to top-posted replies, please don''t ask


Victor Bazarov wrote:

John Doe wrote:

So here is the update code (without the try for new I will do it later)
but now I get an error :
error C2662: ''NetworkList::Clear'' : cannot convert ''this'' pointer from
''const NetworkList'' to ''NetworkList &''

so I have added const to Clear()...
//============================================//
// NetworkManager.h
//============================================//
struct DeletePointer {
template<typename T>
void operator()(const T* ptr) const
{
delete ptr;
}
};

class Network
{
public:
Network() {};
Network(CString const& netName, GUID netguid):
_netname(netName), _netguid(netguid) {}

~Network() {}

CString const& getName() { return _netname; }
GUID getGuid() const { return _netguid; }

private:
CString _netname;
GUID _netguid;
};
class NetworkList
{
typedef std::list<Network*>::iterator NetworkListIt;

public:

NetworkList()
{
}

~NetworkList()
{
Clear();
}

void Clear()
{
for_each( _netlist.begin(), _netlist.end(), DeletePointer ());
}

void Add(Network* network)
{
if (network)
_netlist.push_back(network);
}
const Network* getNetwork(CString const& netNameOrGuid) const
{
if ((netNameOrGuid.GetAt(0) == ''{'') &&
netNameOrGuid.GetLength() == 39)
{
CLSID guid;
if (SUCCEEDED(CLSIDFromString((LPOLESTR)(LPCTSTR)netN ameOrGuid,&guid)))
{
return getNetwork(guid);
}
}
else
{
std::list<Network*>::const_iterator it;
//NetworkListIt it;
for (it = _netlist.begin(); it != _netlist.end(); ++it)
if (!(*it)->getName().CompareNoCase(netNameOrGuid))
return (*it);
}
return NULL;
}

const Network* getNetwork(CLSID guid) const
{
if (!_netlist.empty())
Clear();

std::list<Network*>::const_iterator it;
//NetworkListIt it;
for (it = _netlist.begin(); it != _netlist.end(); ++it)
if ((*it)->getGuid() == guid)
return (*it);

return NULL;
}

private:
std::list<Network*_netlist;
};

//============================================//
// NetworkManager.cpp
//============================================//
NetworkList getNetworkList()
{
NetworkList netList;

// Simulate we retrieve network list from OS
GUID guid;
netList.Add(new Network(_T("Network1"), guid));
netList.Add(new Network(_T("Network2"), guid));

return netList;
}

//============================================//
// Testcase
//============================================//

void OnGettingNetworkList()
{
NetworkList netList = getNetworkList();
}

When the netList is destroyed I get a debug assertion due to CString
object :

void Release() throw()
{
ATLASSERT( nRefs != 0 ); <<<<< !!!!!!!!!

if( _AtlInterlockedDecrement( &nRefs ) <= 0 )
{
pStringMgr->Free( this );
}
}


On Fri, 24 Oct 2008 17:18:15 +0200, John Doe wrote:

Victor Bazarov wrote:

>John Doe wrote:


So here is the update code (without the try for new I will do it later)
but now I get an error :
error C2662: ''NetworkList::Clear'' : cannot convert ''this'' pointer from
''const NetworkList'' to ''NetworkList &''

so I have added const to Clear()...

[snip]

>
void Clear()
{
for_each( _netlist.begin(), _netlist.end(), DeletePointer());
}

How many times is this function called in your test case?
Most probably two times, right?
And what does it do each time?

[snip]

>
void OnGettingNetworkList()
{
NetworkList netList = getNetworkList();
}

You return a *copy* of the NetworkList you build in the function.
The first copy dies and deallocates via Clear() all the pointers so
the copy contains invalid pointers, which are deallocated yet again,
that''s where the CString fails it assertions, becuase it is already
destroyed.

>
When the netList is destroyed I get a debug assertion due to CString
object :

void Release() throw()
{
ATLASSERT( nRefs != 0 ); <<<<< !!!!!!!!!

if( _AtlInterlockedDecrement( &nRefs ) <= 0 ) {
pStringMgr->Free( this );
}
}

--
OU
Remember 18th of June 2008, Democracy died that afternoon.
http://frapedia.se/wiki/Information_in_English


这篇关于这堂课怎么了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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