C ++在hpp文件中声明异常

时间:2017-01-18 18:45:03

标签: c++ visual-c++

我想修改PierreBdR's exception example如何创建自定义异常,以便其他类可见。他的例子适用于我,但例外只在该类中可见。

我使用的是MS Visual Studio 2013,而且我是一个受Java思维困扰的C ++新手。

以下是.hpp文件中的内容:


struct IllegalArgumentException : public std::exception
{
public: IllegalArgumentException(std::string ss);
public: ~IllegalArgumentException();

const char* IllegalArgumentException::what()  { return s.c_str(); }

private: std::string s;

};

以下是.cpp文件的一部分:


IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {}

IllegalArgumentException::~IllegalArgumentException() {}

const char * IllegalArgumentException::what()  { return s.c_str(); }

我得到了:

  • 错误C2011:' IllegalArgumentExcpetion':' struct'类型重新定义(.hpp文件)

4 个答案:

答案 0 :(得分:2)

第1点

exports.true = '#true'
exports['some text'] = 'text'
如果在const char* IllegalArgumentException::what() { return s.c_str(); } class内声明,则

声明不正确。因为声明是在structIllegalArgumentException:: is implied内进行的,并且与编译器混淆,因为编译器现在认为你正在声明其他东西。你想要

IllegalArgumentException

此外,const char* what() { return s.c_str(); } 部分实现了该函数,因此无需在cpp文件中实现它。

第2点

{ return s.c_str(); }中的所有内容均为struct,除非在public关键字后声明。除非另有说明,否则这与private相反,其中所有内容均为classprivateclass除了默认访问权限之外几乎完全相同。

第3点

在C ++中,您可以在块中声明成员的访问级别。无需一次声明一个成员的访问级别。

struct

struct IllegalArgumentException : public std::exception 
{ 
    // these are all public by default in a struct
    IllegalArgumentException(std::string ss); 
   ~IllegalArgumentException(); 
    const char* IllegalArgumentException::what() { return s.c_str(); } 
private: // everything after this is private
    std::string s; 
    int example; 
}; 

class IllegalArgumentException : public std::exception 
{ 
public: // these are all private by default in a class and need to be public
    IllegalArgumentException(std::string ss); 
   ~IllegalArgumentException(); 
    const char* IllegalArgumentException::what() { return s.c_str(); }
private: // switch back to private
    std::string s; 
    int example; 
}; 

第4点

class IllegalArgumentException : public std::exception 
{ 
    // these are all private by default in a class
    std::string s; 
    int example; 
public: // everything after this is public
    IllegalArgumentException(std::string ss); 
   ~IllegalArgumentException(); 
    const char* IllegalArgumentException::what() { return s.c_str(); }
}; 

没有做任何事情。它不需要做任何事情,因此Rule of Zero建议不要使用析构函数。编译器将为您创建它。如果您不必编写它,请不要编写它,因为不存在的代码没有错误。

IllegalArgumentException::~IllegalArgumentException() {}

第5点

此处从KerrekSB窃取,因为OP提出了另一个问题。 Use Include Guards

包含防护可防止在同一translation unit中多次包含标头。这是一个问题,因为膨胀和同一事物被定义或宣布不止一次的可能性导致混淆哪个是真实的。

一个简单的头球卫士:

class IllegalArgumentException : public std::exception 
{ 
    // these are all private by default 
    std::string s; 
    int example; 
public: // everything after this is public
    IllegalArgumentException(std::string ss); 
    const char* IllegalArgumentException::what() { return s.c_str(); }
}; 

您也可以使用#ifndef ILLEGALARGUMENTEXCEPTION_H // if we've never seen ILLEGALARGUMENTEXCEPTION_H // before, do the following #define ILLEGALARGUMENTEXCEPTION_H // OK we've seen it now! // all subsequent includes of IllegalArgumentException.h will have seen // ILLEGALARGUMENTEXCEPTION_H and fail the ifndef, skipping everything // until it finds the closing #endif #include <string> #include <exception> class IllegalArgumentException : public std::exception { // these are all private by default std::string s; int example; public: // everything after this is public IllegalArgumentException(std::string ss); const char* IllegalArgumentException::what() { return s.c_str(); } }; #endif // end of Include Guard ,但要注意#pragma once表示非标准编译器扩展。您的编译器可能不存在#pragma,如果没有,编译器可以跳过指令而不告诉您!

once不在标准中的原因有很多,最重要的是它有unresolved fail cases。请谨慎使用。

答案 1 :(得分:1)

您混淆了what()函数的声明和定义。您尝试使用范围分辨率运算符(即 :: )引用该函数。在这种情况下,它应该在定义中(即在.cpp文件中)

完成

同样,what()功能在 .hpp 文件中实现为内嵌功能,这意味着您无需再次在 .cpp 文件。因此,您收到redefinition of ‘const char* IllegalArgumentException::what()错误。

P.S:在C ++类声明中,不需要指定每个属性/方法的访问修饰符,您只需将它们分组到单个修饰符下即可。

.hpp文件:

struct IllegalArgumentException : public std::exception
{
public: 
 IllegalArgumentException(std::string ss);
~IllegalArgumentException();

const char* what()  { return s.c_str(); }

private: 
 std::string s;

};

.cpp文件:

IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {}

IllegalArgumentException::~IllegalArgumentException() {}

答案 2 :(得分:0)

我不确定,但我可以评论......

我认为你的“what”功能是两次实现的: 先在你的hpp文件中,然后在cpp文件中。

答案 3 :(得分:0)

看起来你可能,也许是间接的,包括.hpp文件不止一次?

#include是一种在几个.cpp文件之间共享代码的相当原始的方式:它告诉编译器(具体来说是预处理器)在代码中的那个位置导入.hpp的内容。然后在稍后的传递中,编译器将编译整个事物,就像它是一个文件一样。 (对于该预处理器步骤,有一个完全疯狂的图灵完整语言; IMO你应该尽可能地避免使用它,大多只使用它来处理本笔记中概述的内容。)

这种方法的一个问题是,如果您最终导入一个.hpp文件不止一次 - 这是一件非常常见的事情,因为.hpp文件通常包含其他.hpp文件 - 您将重复该代码。不止一次定义结构或类是非法的,因此您会收到有关“类型重新定义”的错误。

解决方案是在每个.hpp文件中使用包含保护。在最顶部,使用如下行:

#ifndef SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER
#define SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER

然后在.hpp文件的最底部:

#endif  // SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER

如果已经定义了大的唯一字符串,那些预处理器指令#ifndef#define等将删除中间的任何文本。通常,您的代码库将为该大字符串建立约定,例如将路径编码到其中。我的公司甚至使用一个lint工具来确保你正确编码它。

这确保了如果#include .hpp两次,或#include包含已包含的.hpp的另一个.hpp,您将在最终的预处理器输出中获得.hpp文件的内容一次。

这和一般的预处理器是C ++中不那么迷人的部分之一,它真正展示了它的时代。很快,语言将变得更加现代和愉快,用于共享称为“模块”的接口。与此同时,每个.hpp都需要这3行样板。