一段简单的C++代码在VC6.0没问题,但是在VC2017出错,求分析原因!

uouo88 2019-03-04 04:57:53


如图,在VC6.0中没有问题,在VC2017编译出错,试了一下,只要把public CExpetcion 改成 protected CExpetcion,或者将throw BatchException("~ServiceHandle"); 改为 throw new BatchException("~ServiceHandle"); 就没有这个link报错的问题,为什么throw普通对象的时候会去触发CObject的复制构造方法?求分析原因!
...全文
269 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
pstrunner 2019-03-05
  • 打赏
  • 举报
回复
引用 10 楼 uouo88 的回复:
[quote=引用 8 楼 pstrunner 的回复:]

void main()
{
	CMyException tst("hello"), tst2;
	// 没有问题
	tst2 = tst;
	// 报错
	throw tst;
}
是的,我用你的代码试了,这里只要加上throw tst;就出错,可是为什么呢,你前main函数里面两句代码分别测试了构造方法和赋值构造方法,都没有问题,甚至我在你代码的基础上,“throw tst; ”前加上一句CMyException tst3(tst2);再编译也是没有问题的,说明单独调用拷贝构造函数也不会错。[/quote] 我在上面已经回答了,估计是VC问题,你参考下面的说明: The throw of an instance of a class object causes a copy to be generated when the object is copied into the C++ runtime memory location that holds the exception object. It may be possible for some compilers to "elide" (get rid of) this call to the copy-constructor in a similar way to which they can get rid of the call to a copy-constructor when returning an instance of a class object from a function (the RVO optimization) - but the compiler still needs to check that the copy-constructor is callable: so if the copy-constructor is private it should still cause an error even though the compiler would not actually generate a call to it.
uouo88 2019-03-05
  • 打赏
  • 举报
回复
引用 8 楼 pstrunner 的回复:

void main()
{
CMyException tst("hello"), tst2;
// 没有问题
tst2 = tst;
// 报错
throw tst;
}


是的,我用你的代码试了,这里只要加上throw tst;就出错,可是为什么呢,你前main函数里面两句代码分别测试了构造方法和赋值构造方法,都没有问题,甚至我在你代码的基础上,“throw tst; ”前加上一句CMyException tst3(tst2);再编译也是没有问题的,说明单独调用拷贝构造函数也不会错。
uouo88 2019-03-05
  • 打赏
  • 举报
回复
补充测试代码如下

#include "pch.h"
#include "afx.h"
#include <iostream>
using namespace std;

class BaseException
{
public:
BaseException() throw() {cout << "Constructor BaseException() is called" << endl;}
~BaseException() throw() { cout << "Destructor ~BaseException() is called" << endl; }
//virtual ~BaseException() = 0;
private:
BaseException(const BaseException& be) throw() // = delete;
{
cout << "Copy-Constructor BaseException(const BaseException& be) is called" << endl;
}
};

class BatchException : public BaseException //public CException
{
private:
CString m_cdMsg = "";
public:
BatchException() throw() { cout << "Constructor BatchException() is called" << endl; }
BatchException(const char* p_szMes) throw()
{
m_cdMsg = p_szMes;
cout << "Constructor BatchException(const char* p_szMes) is called" << endl;
}
BatchException(const BatchException& be) throw()
{
this->m_cdMsg = be.m_cdMsg;
cout << "Copy-Constructor BatchException(const BatchException& be) is called" << endl;
}
const BatchException& operator = (const BatchException& be) throw()
{
this->m_cdMsg = be.m_cdMsg; return *this;
cout << "Assign-Constructor BatchException(const BatchException& be) is called" << endl;
}
virtual ~BatchException() throw() { cout << "Destructor ~BatchException() is called" << endl; }
virtual const char *what() const throw() { return m_cdMsg; }
};

int main()
{
try
{
//BatchException be("BatchException occurs");
//throw be;
throw BatchException("BatchException occurs");
//throw new BatchException("BatchException occurs");
}
catch (BatchException& e)
{
cout << "e.what() = " <<e.what() << endl;
}
//catch (CException* e)
//{
// cout << "e->what() = " << ((BatchException*)e)->what() << endl;
// e->Delete();
//}
//pause:
getchar();
}
pstrunner 2019-03-05
  • 打赏
  • 举报
回复

void main()
{
	CMyException tst("hello"), tst2;
	// 没有问题
	tst2 = tst;
	// 报错
	throw tst;
}
pstrunner 2019-03-05
  • 打赏
  • 举报
回复
我也写了测试代码:

class CMyException : public CException
{
public:
	CMyException() {}
	CMyException(const CMyException& x) {
		*this = x;
	}
	explicit CMyException(const char* szMsg) {}
	~CMyException() {}
	CMyException& operator=(const CMyException& x) {
		return *this;
	}
private:

};
uouo88 2019-03-05
  • 打赏
  • 举报
回复
引用 5 楼 pstrunner 的回复:
[quote=引用 4 楼 uouo88 的回复:]
[quote=引用 3 楼 pstrunner 的回复:]
我查了下,估计这是VC的一个问题,msdn论坛解释如下:【https://social.msdn.microsoft.com/Forums/vstudio/en-US/a7dfa49c-6b81-4ce1-86a3-a926c700d626/yet-another-c2248-error?forum=vcgeneral】

The throw of an instance of a class object causes a copy to be generated when the object is copied into the C++ runtime memory location that holds the exception object.

It may be possible for some compilers to "elide" (get rid of) this call to the copy-constructor in a similar way to which they can get rid of the call to a copy-constructor when returning an instance of a class object from a function (the RVO optimization) - but the compiler still needs to check that the copy-constructor is callable: so if the copy-constructor is private it should still cause an error even though the compiler would not actually generate a call to it.

If you throw a pointer to an object, as in your code, then you need to catch a pointer. For example:

class X { };

void f()
{
throw new X();
}

void g()
{
try {
f();
}
catch (X* pX) {
delete pX;
}
}

Note: as object to be thrown is dynamically allocated you need to delete it otherwise you will have a memory leak.



可是throw对象的时候为啥是去看CObject的private的拷贝构造函数呢?难道不是应该调用BatchException这个类的拷贝构造函数吗?[/quote]
在affx.h文件里,CException是继承CObject的。
class AFX_NOVTABLE CException : public CObject
[/quote]

我写了一个测试类A继承测试类B,且都加上了拷贝构造方法和cout测试语句,在main函数throw A的对象实例,然后B类的拷贝构造方法测试结果显示并没有调用到.
pstrunner 2019-03-05
  • 打赏
  • 举报
回复
引用 4 楼 uouo88 的回复:
[quote=引用 3 楼 pstrunner 的回复:] 我查了下,估计这是VC的一个问题,msdn论坛解释如下:【https://social.msdn.microsoft.com/Forums/vstudio/en-US/a7dfa49c-6b81-4ce1-86a3-a926c700d626/yet-another-c2248-error?forum=vcgeneral】 The throw of an instance of a class object causes a copy to be generated when the object is copied into the C++ runtime memory location that holds the exception object. It may be possible for some compilers to "elide" (get rid of) this call to the copy-constructor in a similar way to which they can get rid of the call to a copy-constructor when returning an instance of a class object from a function (the RVO optimization) - but the compiler still needs to check that the copy-constructor is callable: so if the copy-constructor is private it should still cause an error even though the compiler would not actually generate a call to it. If you throw a pointer to an object, as in your code, then you need to catch a pointer. For example: class X { }; void f() { throw new X(); } void g() { try { f(); } catch (X* pX) { delete pX; } } Note: as object to be thrown is dynamically allocated you need to delete it otherwise you will have a memory leak.
可是throw对象的时候为啥是去看CObject的private的拷贝构造函数呢?难道不是应该调用BatchException这个类的拷贝构造函数吗?[/quote] 在affx.h文件里,CException是继承CObject的。
class AFX_NOVTABLE CException : public CObject
uouo88 2019-03-04
  • 打赏
  • 举报
回复
引用 3 楼 pstrunner 的回复:
我查了下,估计这是VC的一个问题,msdn论坛解释如下:【https://social.msdn.microsoft.com/Forums/vstudio/en-US/a7dfa49c-6b81-4ce1-86a3-a926c700d626/yet-another-c2248-error?forum=vcgeneral】

The throw of an instance of a class object causes a copy to be generated when the object is copied into the C++ runtime memory location that holds the exception object.

It may be possible for some compilers to "elide" (get rid of) this call to the copy-constructor in a similar way to which they can get rid of the call to a copy-constructor when returning an instance of a class object from a function (the RVO optimization) - but the compiler still needs to check that the copy-constructor is callable: so if the copy-constructor is private it should still cause an error even though the compiler would not actually generate a call to it.

If you throw a pointer to an object, as in your code, then you need to catch a pointer. For example:

class X { };

void f()
{
throw new X();
}

void g()
{
try {
f();
}
catch (X* pX) {
delete pX;
}
}

Note: as object to be thrown is dynamically allocated you need to delete it otherwise you will have a memory leak.



可是throw对象的时候为啥是去看CObject的private的拷贝构造函数呢?难道不是应该调用BatchException这个类的拷贝构造函数吗?
pstrunner 2019-03-04
  • 打赏
  • 举报
回复
我查了下,估计这是VC的一个问题,msdn论坛解释如下:【https://social.msdn.microsoft.com/Forums/vstudio/en-US/a7dfa49c-6b81-4ce1-86a3-a926c700d626/yet-another-c2248-error?forum=vcgeneral】 The throw of an instance of a class object causes a copy to be generated when the object is copied into the C++ runtime memory location that holds the exception object. It may be possible for some compilers to "elide" (get rid of) this call to the copy-constructor in a similar way to which they can get rid of the call to a copy-constructor when returning an instance of a class object from a function (the RVO optimization) - but the compiler still needs to check that the copy-constructor is callable: so if the copy-constructor is private it should still cause an error even though the compiler would not actually generate a call to it. If you throw a pointer to an object, as in your code, then you need to catch a pointer. For example: class X { }; void f() { throw new X(); } void g() { try { f(); } catch (X* pX) { delete pX; } } Note: as object to be thrown is dynamically allocated you need to delete it otherwise you will have a memory leak.
uouo88 2019-03-04
  • 打赏
  • 举报
回复
引用 1 楼 pstrunner 的回复:
你要看看是否存在public的CException的构造函数,我看到报错是因为private的Cobject构造函数不存在。


我看了一下,CException类的public的构造函数是存在的,但是CException继承了CObject类,CObject的拷贝构造方法是private并且标注未实现的。
然后我对比了一下VC6.0的CException和VC2017的CException,虽然都标注为抽象类,但是VC6.0的CException是可以用构造方法初始化的,但是VC2017的CException不能用它的构造方法初始化,错误提示CException是一个抽象类,不能被实例化。
pstrunner 2019-03-04
  • 打赏
  • 举报
回复
你要看看是否存在public的CException的构造函数,我看到报错是因为private的Cobject构造函数不存在。

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧