2009-11-03 81 views

回答

50

有最接近的事就是打电话typeid(your_class).name() - 但这会产生编译器的具体重整名称。

要使用它的内部类只是typeid(*this).name()

+0

谢谢..这是一个好足够的日志 – mortal 2009-11-03 11:47:40

+0

你要知道你的类首先要调用此;-) – 2009-11-03 11:48:18

+0

这是记录,所以我知道我在哪里调用这个类。试图避免显式定义一个包含类名称的char数组 – mortal 2009-11-03 11:51:54

9

尚未。 (我认为__class__是在某处提出的)。您也可以尝试从__PRETTY_FUNCTION__中提取课程部分。

3

如果编译器恰好是g++和你所要求的__CLASS__因为你想办法让当前的方法名,包括类,__PRETTY_FUNCTION__应(根据info gcc,部分5.43函数名称作为字符串)帮助。

55

使用typeid(*this).name()的问题是在静态方法调用中没有this指针。宏__PRETTY_FUNCTION__报告在静态函数和方法调用的类名。但是,这只会与gcc一起使用。

这里是通过提取宏风格的界面信息的一个例子。

inline std::string methodName(const std::string& prettyFunction) 
{ 
    size_t colons = prettyFunction.find("::"); 
    size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1; 
    size_t end = prettyFunction.rfind("(") - begin; 

    return prettyFunction.substr(begin,end) + "()"; 
} 

#define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__) 

__METHOD_NAME__将返回形式<class>::<method>()的字符串,从什么__PRETTY_FUNCTION__给你修剪的返回类型,修饰符和参数。

对于一些中提取只是类的名称,有些必须小心陷阱的情况下没有课:

inline std::string className(const std::string& prettyFunction) 
{ 
    size_t colons = prettyFunction.find("::"); 
    if (colons == std::string::npos) 
     return "::"; 
    size_t begin = prettyFunction.substr(0,colons).rfind(" ") + 1; 
    size_t end = colons - begin; 

    return prettyFunction.substr(begin,end); 
} 

#define __CLASS_NAME__ className(__PRETTY_FUNCTION__) 
+4

不应该用'#ifdef __GNU_C__'来包围它吗? – einpoklum 2014-03-22 13:35:21

+1

而不是'substr(0,colons).rfind(“”)''可以使用'rfind(',colons)'来创建一个额外的串。 – mariusm 2014-10-13 06:47:43

+1

我宁愿使用find_last_of(“::”)否则函数将只返回一个名称空间,如果有一个 – underdoeg 2014-12-18 22:28:58

4

我认为使用__PRETTY_FUNCTION__是不够好,尽管它包含命名空间以及即namespace::classname::functionname直到__CLASS__可用。

1

你可以得到包含类名的函数名。 这可以处理C型功能。

static std::string methodName(const std::string& prettyFunction) 
{ 
    size_t begin,end; 
    end = prettyFunction.find("("); 
    begin = prettyFunction.substr(0,end).rfind(" ") + 1; 
    end -= begin; 
    return prettyFunction.substr(begin,end) + "()"; 
} 
1

我的解决办法:

std::string getClassName(const char* fullFuncName) 
{ 
    std::string fullFuncNameStr(fullFuncName); 
    size_t pos = fullFuncNameStr.find_last_of("::"); 
    if (pos == std::string::npos) 
    { 
     return ""; 
    } 
    return fullFuncNameStr.substr(0, pos-1); 
} 

#define __CLASS__ getClassName(__FUNCTION__) 

我工程的Visual C++ 12。

1

下面是基于该__FUNCTION__宏观和C++模板的溶液:

template <class T> 
class ClassName 
{ 
public: 
    static std::string Get() 
    { 
    // Get function name, which is "ClassName<class T>::Get" 
    // The template parameter 'T' is the class name we're looking for 
    std::string name = __FUNCTION__; 
    // Remove "ClassName<class " ("<class " is 7 characters long) 
    size_t pos = name.find_first_of('<'); 
    if (pos != std::string::npos) 
     name = name.substr(pos + 7); 
    // Remove ">::Get" 
    pos = name.find_last_of('>'); 
    if (pos != std::string::npos) 
     name = name.substr(0, pos); 
    return name; 
    } 
}; 

template <class T> 
std::string GetClassName(const T* _this = NULL) 
{ 
    return ClassName<T>::Get(); 
} 

下面是如何可以被用于记录器类

template <class T> 
class Logger 
{ 
public: 
    void Log(int value) 
    { 
    std::cout << GetClassName<T>() << ": " << value << std::endl; 
    std::cout << GetClassName(this) << ": " << value << std::endl; 
    } 
}; 

class Example : protected Logger<Example> 
{ 
public: 
    void Run() 
    { 
    Log(0); 
    } 
} 
示例

Example::Run的输出将是

Example: 0 
Logger<Example>: 0 
+0

请注意,如果你有一个指向基的指针(这可能是好的),这将不考虑多态。 – 2015-01-22 12:31:38

0

这个工程相当不错,如果你愿意支付指针的成本。

class State 
{ 
public: 
    State(const char* const stateName) :mStateName(stateName) {}; 
    const char* const GetName(void) { return mStateName; } 
private: 
    const char * const mStateName; 
}; 

class ClientStateConnected 
    : public State 
{ 
public: 
    ClientStateConnected(void) : State(__FUNCTION__) {}; 
}; 
7

我想建议boost::typeindex,这是我了解到的,斯科特·迈尔的 “有效的现代C++” 这是一个基本的例子:

#include <boost/type_index.hpp> 

class foo_bar 
{ 
    int whatever; 
}; 

namespace bti = boost::typeindex; 

template <typename T> 
void from_type(T t) 
{ 
    std::cout << "\tT = " << bti::type_id_with_cvr<T>().pretty_name() << "\n"; 
} 

int main() 
{ 
    std::cout << "If you want to print a template type, that's easy.\n"; 
    from_type(1.0); 
    std::cout << "To get it from an object instance, just use decltype:\n"; 
    foo_bar fb; 
    std::cout << "\tfb's type is : " 
       << bti::type_id_with_cvr<decltype(fb)>().pretty_name() << "\n"; 
} 

编译与“G ++ - -std = C++ 14“产生以下内容

输出

如果要打印模板类型,那很简单。

T =双

从一个对象实例得到它,只需使用decltype:

FB的类型是:foo_bar这样

+0

是否有可能得到没有名称空间的类名?又名http://coliru.stacked-crooked.com/a/cf1b1a865bb7ecc7 – tower120 2016-02-18 16:31:18

0

与MSVC和gcc太

#ifdef _MSC_VER 
#define __class_func__ __FUNCTION__ 
#endif 

#ifdef __GNUG__ 
#include <cxxabi.h> 
#include <execinfo.h> 
char *class_func(const char *c, const char *f) 
{ 
    int status; 
    static char buff[100]; 
    char *demangled = abi::__cxa_demangle(c, NULL, NULL, &status); 
    snprintf(buff, sizeof(buff), "%s::%s", demangled, f); 
    free(demangled); 
    return buff; 
} 
#define __class_func__ class_func(typeid(*this).name(), __func__) 
#endif 
0

以下方法(基于上面的methodName())也可以处理像“int main(int argc,char ** argv)”这样的输入:

string getMethodName(const string& prettyFunction) 
{ 
    size_t end = prettyFunction.find("(") - 1; 
    size_t begin = prettyFunction.substr(0, end).rfind(" ") + 1; 

    return prettyFunction.substr(begin, end - begin + 1) + "()"; 
}