D
Dmitry Prokoptsev
Hello,
I need to write a class for exceptions which can be thrown, caught,
stored and thrown once again. I have written the following code:
--- begin ---
#include <string>
class Exception {
public:
virtual ~Exception() throw() {}
virtual const char* what() const throw() = 0;
virtual void raise() = 0;
};
class RuntimeError: public Exception {
public:
RuntimeError(const std::string& what): what_(what) {}
const char* what() const throw() { return what_.c_str(); }
void raise() { throw *this; }
private:
std::string what_;
};
template<class Self, class Base> class ExceptionImpl: public Base {
public:
typedef ExceptionImpl<Self, Base> Impl;
void raise() { throw *this; }
template<class A> ExceptionImpl(A a): Base(a) {}
// ExceptionImpl(const Self& self): Base(self) {}
};
class AbstractError: public RuntimeError {
public:
AbstractError(const std::string& what): RuntimeError(what) {}
virtual void foo() = 0;
};
class ConcreteError: public ExceptionImpl<ConcreteError, AbstractError>
{
public:
ConcreteError(const std::string& what): Impl(what) {}
void foo() {}
};
int main()
{
ConcreteError c("foo");
return 0;
}
--- end ---
....and received those strange compiler messages (Microsoft Visual C++
2005):
--- begin ---
Compiling...
exceptions.cpp
c:\src\temp\exceptions\exceptions.cpp : warning C4717:
'ConcreteError::ConcreteError' : recursive on all control paths,
function will cause runtime stack overflow
Linking...
exceptions.obj : error LNK2019: unresolved external symbol "public:
__thiscall ExceptionImpl<class ConcreteError,class
AbstractError>::ExceptionImpl<class ConcreteError,class
AbstractError>(class ExceptionImpl<class ConcreteError,class
AbstractError> const &)"
(??0?$ExceptionImpl@VConcreteError@@VAbstractError@@@@QAE@ABV0@@Z)
referenced in function "public: virtual void __thiscall
ExceptionImpl<class ConcreteError,class AbstractError>::raise(void)"
(?raise@?$ExceptionImpl@VConcreteError@@VAbstractError@@@@UAEXXZ)
exceptions.obj : error LNK2001: unresolved external symbol "public:
virtual void * __thiscall ExceptionImpl<class ConcreteError,class
AbstractError>::`scalar deleting destructor'(unsigned int)"
(??_G?$ExceptionImpl@VConcreteError@@VAbstractError@@@@UAEPAXI@Z)
exceptions.obj : error LNK2001: unresolved external symbol "public:
virtual void * __thiscall ExceptionImpl<class ConcreteError,class
AbstractError>::`vector deleting destructor'(unsigned int)"
(??_E?$ExceptionImpl@VConcreteError@@VAbstractError@@@@UAEPAXI@Z)
C:\src\temp\exceptions\Debug\exceptions.exe : fatal error LNK1120: 3
unresolved externals
--- end ---
If I uncomment the commented constructor in ExceptionImpl,
ConcreteError::ConcreteError() stops to be recursive, but what compiler
wants from me when it complains about absence of `scalar deleting
destructor'?
Linker messages disappear if pure virtual function AbstractError::foo()
is removed or replaced with non-pure or non-virtual, or if body of
function ExceptionImpl::raise() is replaced with empty one.
gcc3 seem to handle this without any warnings, so what's wrong with
this code?
Thanks in advance.
I need to write a class for exceptions which can be thrown, caught,
stored and thrown once again. I have written the following code:
--- begin ---
#include <string>
class Exception {
public:
virtual ~Exception() throw() {}
virtual const char* what() const throw() = 0;
virtual void raise() = 0;
};
class RuntimeError: public Exception {
public:
RuntimeError(const std::string& what): what_(what) {}
const char* what() const throw() { return what_.c_str(); }
void raise() { throw *this; }
private:
std::string what_;
};
template<class Self, class Base> class ExceptionImpl: public Base {
public:
typedef ExceptionImpl<Self, Base> Impl;
void raise() { throw *this; }
template<class A> ExceptionImpl(A a): Base(a) {}
// ExceptionImpl(const Self& self): Base(self) {}
};
class AbstractError: public RuntimeError {
public:
AbstractError(const std::string& what): RuntimeError(what) {}
virtual void foo() = 0;
};
class ConcreteError: public ExceptionImpl<ConcreteError, AbstractError>
{
public:
ConcreteError(const std::string& what): Impl(what) {}
void foo() {}
};
int main()
{
ConcreteError c("foo");
return 0;
}
--- end ---
....and received those strange compiler messages (Microsoft Visual C++
2005):
--- begin ---
Compiling...
exceptions.cpp
c:\src\temp\exceptions\exceptions.cpp : warning C4717:
'ConcreteError::ConcreteError' : recursive on all control paths,
function will cause runtime stack overflow
Linking...
exceptions.obj : error LNK2019: unresolved external symbol "public:
__thiscall ExceptionImpl<class ConcreteError,class
AbstractError>::ExceptionImpl<class ConcreteError,class
AbstractError>(class ExceptionImpl<class ConcreteError,class
AbstractError> const &)"
(??0?$ExceptionImpl@VConcreteError@@VAbstractError@@@@QAE@ABV0@@Z)
referenced in function "public: virtual void __thiscall
ExceptionImpl<class ConcreteError,class AbstractError>::raise(void)"
(?raise@?$ExceptionImpl@VConcreteError@@VAbstractError@@@@UAEXXZ)
exceptions.obj : error LNK2001: unresolved external symbol "public:
virtual void * __thiscall ExceptionImpl<class ConcreteError,class
AbstractError>::`scalar deleting destructor'(unsigned int)"
(??_G?$ExceptionImpl@VConcreteError@@VAbstractError@@@@UAEPAXI@Z)
exceptions.obj : error LNK2001: unresolved external symbol "public:
virtual void * __thiscall ExceptionImpl<class ConcreteError,class
AbstractError>::`vector deleting destructor'(unsigned int)"
(??_E?$ExceptionImpl@VConcreteError@@VAbstractError@@@@UAEPAXI@Z)
C:\src\temp\exceptions\Debug\exceptions.exe : fatal error LNK1120: 3
unresolved externals
--- end ---
If I uncomment the commented constructor in ExceptionImpl,
ConcreteError::ConcreteError() stops to be recursive, but what compiler
wants from me when it complains about absence of `scalar deleting
destructor'?
Linker messages disappear if pure virtual function AbstractError::foo()
is removed or replaced with non-pure or non-virtual, or if body of
function ExceptionImpl::raise() is replaced with empty one.
gcc3 seem to handle this without any warnings, so what's wrong with
this code?
Thanks in advance.