2017-01-18 45 views
-1

我想修改PierreBdR's exception example如何制作自定义异常,以便其他类可见。他的例子适用于我,但例外情况仅在该类中可见。C++在hpp文件中声明异常

我使用MS Visual Studio 2013,我是一个C++新手,受到Java心态的阻碍。

这里是什么在.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文件)
+1

首先,你的cpp文件中的what()应该是IllegalArgumentException :: what()。 – 0x5453

+0

@ 0x5453,谢谢。修改代码后,只剩下一个错误。 – ssimm

+2

你忘记了标题周围的守卫。 –

回答

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文件:如果一个或classstruct内声明

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

IllegalArgumentException::~IllegalArgumentException() {} 
0

我不知道,但我可以发表评论......如此

我想你“是什么”的功能是实现了两个时代: 首先在你的HPP文件,然后在cpp文件。

2

点1

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

被错误地声明。由于声明是在IllegalArgumentException类,IllegalArgumentException:: is implied内部编译的,因为编译器现在认为你在声明别的东西。你想

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

此外,{ return s.c_str(); }部分实现的功能,所以没有必要实现它在cpp文件。

点2

struct一切public除非宣布继private关键字。除非另有说明,否则这与class相反,其中一切均为private。一个class和一个struct几乎是相同的,除了默认访问的区别。

点3

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

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; 
}; 

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

4点

IllegalArgumentException::~IllegalArgumentException() {} 

没有做任何事情。它不需要做任何事情,所以Rule of Zero建议不要有析构函数。编译器会为你创建它。如果你不必写它,不要写它,因为不存在的代码没有错误。

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

点5

从KerrekSB这里偷窃,因为它是一个点,OP对另外一个问题。 Use Include Guards

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

一个简单的头文件保护:

#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,如果不存在,编译器可以不告诉你跳过指令

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

+0

你给我所有这些好的提示是非常友好的(我已经重读过几次)。但是我必须奖励czimbortibor的答案,因为他的答案更符合极简主义和可验证的理想。 – ssimm

+0

@ssimm不是问题。与问题直接相关的唯一一点是第1点,czimbortibor更详细地解释了这一点。 – user4581301

0

看起来你可能或许间接地多次包括.hpp文件?

#include是在几个.cpp文件之间共享代码的一种相当原始的方式:它告诉编译器(特别是预处理器)在代码中的那个位置导入.hpp的内容。然后在稍后的过程中,编译器会将整个事物编译为一个文件。 (对于该预处理步骤,有一个完整的疯狂图灵完整语言; IMO应该尽可能避免它,大多数情况下只用于本说明中概述的内容。)

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

解决方法是在每个.hpp文件中使用include guard。在最高层,用线,如:

#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需要这三行样板。

+0

ht。 Kerrek SB和其他推断失踪的人包括警卫。 – ech