Archived

This topic is now archived and is closed to further replies.

sflare

how to get classname?

Recommended Posts

i would like to beable to get the name of the class in the function code from the class automatically (c++). Anyone know how? (if it''s possible) example: class MYCLASS { void my_function() { printf("%s",GET_CURRENT_CLASSNAME); <<<<---- HERE } }; where GET_CURRENT_CLASSNAME would give something like "MYCLASS" it would be something like the MACRO __LINE__ i think i remember reading other ones for function names.... Thanks

Share this post


Link to post
Share on other sites
I was just quickly reading about

UnDecorateSymbolName()
it seems using UNDNAME_NAME_ONLY may help for this problem

also would need
BOOL SymGetSymFromAddr(
HANDLE hProcess,
DWORD Address,
PDWORD Displacement,
PIMAGEHLP_SYMBOL Symbol
);

to get the decorated name in the first place, right?

Share this post


Link to post
Share on other sites
If there is one for function names, I don''t know about it. But you could write a macro yourself:


std::string g_sFuncName;
#define FUNC( func ) func { g_sFuncName = #func;

...

HRESULT FUNC( Fap::Foo( int bar, float baz ) )
// do stuff
printf( "%s", g_sFuncName );
}


It''s not pretty (it kills the open brace ''{'') but it''ll work.

I like pie.

Share this post


Link to post
Share on other sites
UndecorateSymbolName and all that stuff won''t help here. That''s for undoing the symbol name mangling done by C++ compilers when retrieving a symbol from a DLL.

Can you clarify what you want exactly? Do you want a macro that will generate the class name automatically at compile time, maybe for debugging purposes? Or do you want to be able to check an object''s class at runtime? (like Java''s instanceof operator, if you''re familiar with Java)

If it''s the first one, I don''t think there''s an easy way to do that in C++, possibly not any way at all. If what you really want is the second option, there are ways. You need to enable RTTI and use typeid or dynamic_cast. Google with some combination of keywords: C++ RTTI dynamic_cast typeid

Share this post


Link to post
Share on other sites
I might be saying something stupid, but... why not write the class name yourself? It''s not prone to change too much anyway, or if it is going to, simply #define it beforehand?

Like :


class MYCLASS
{
void my_function()
{
printf("%s", "MYCLASS");
}
};

//or :


#define CLASSNAME MYCLASS
#define sCLASSNAME "MYCLASS"

class CLASSNAME
{
void my_function()
{
printf("%s",sCLASSNAME);
}
};



ToohrVyk

Share this post


Link to post
Share on other sites
quote:
Original post by sflare
i would like to beable to get the name of the class in the function code from the class automatically (c++).
Anyone know how? (if it''s possible)

Strictly speaking, its not possible. Once a C++ program is compiled, much useful information is removed in the name of efficiency, including most meta-information about the types within your program. Some meta-information is retained for RTTI purposes. If you wish to retain information beyond what RTTI provides, you must build your own Meta-Object Protocol. Perhaps you should describe the problem you think requires this as a solution, and someone will point you in the direction of prior art for solving the problem.

Share this post


Link to post
Share on other sites
Actually, it is possible.

There's an operator called "typeid" which will return a
"const type_info&"-Object of the "type_info"-Class.

The "type_info"-Class has a member-function
'const char* name() const' which will give
you the class name.

typeid [msdn online]
type_info [msdn online]
[both links only work in IE sadly]

edit:
quote:

From MSDN:
Type information is generated for polymorphic classes only if the /GR (Enable Run-Time Type Information) compiler option is specified.


Without those is seems to be working fine without RTTI even.

[edited by - Wildfire on July 2, 2003 9:23:30 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Wildfire
Actually, it is possible.

There's an operator called "typeid" which will return a "const type_info&"-Object of the "type_info"-Class.

The "type_info"-Class has a member-function 'const char* name() const' which will give you the class name.

It gives you *a* name, which is not guaranteed to be *the* name. As you acknowledge, the class also needs to be polymorphic, which isn't the case with the OP's example. Depending on the actual problem, those details might be a non-issue, which is why I asked what the problem is.

[edited by - SabreMan on July 2, 2003 9:29:42 AM]

Share this post


Link to post
Share on other sites
quote:

As you acknowledge, the class also needs to be polymorphic



No, I did not say that. My quote from MSDN says that you need to enable RTTI if you want to use typeid with polymorphic classes. Otherwise you need not enable RTTI (All of this applies to VisualC++, but since it says 'C++ specific' it should be valid for other compilers too)

And, it does give you the name of the class, not just any name. I've used it myself, even works with STL/Templates!
For example:


std::vector<char> charVector;

std::cout << typeid(charVector).name();


will result in "class std::vector <char,class std::allocator <char> >" as output .

edit: freaking pointy brackets...

[edited by - Wildfire on July 2, 2003 9:52:52 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Wildfire
And, it does give you the name of the class, not just any name. I''ve used it myself


That isn''t guaranteed by the standard. What you''re describing is microsoft specific behaviour. Yes, it''s pedantic but yes it''s true. And pedantry gets you a long way when trying to write portable code.

Share this post


Link to post
Share on other sites
quote:
Original post by Wildfire
No, I did not say that.

I didn''t claim *you* said that, I said you acknowledged it. You provided a quote from MSDN which I took as acknowledgement on your part. Are you now disagreeing with the quote you provided?
quote:

My quote from MSDN says that you need to enable RTTI if you want to use typeid with polymorphic classes .

Sigh... the OP''s example class is *not* polymorphic!
quote:

And, it does give you the name of the class, not just any name.

Your opinion is wrong. I''ve used RTTI under many different compilers, including MSVC, BorlandC++, GCC, Comeau and IBM. There are several different RTTI naming schemes used across those compilers, and all schemes are compliant with the C++ Standard''s requirement for returning `an implementation-defined NTBS'' (Null-Terminated Multibyte String) [18.5.1]. What that means is, if you assume this code:

struct C
{
virtual ~C() {}
};
assert(std::string(typeid(C).name()) == std::string("C"));

The assertion may or may not work, depending on the compiler you are using. It fails on MSVC++6, which returns `struct C''.

Share this post


Link to post
Share on other sites
Hm... it says
"C++ Specific —>" ... "END C++ Specific"

in my MSDN

not "Microsoft Specific -->" ... "END Microsoft Specific"

So, blame MS for handing out wrong information then
(Or rather maybe, for not including enough information)

SabreMan: Please read my post properly. I said: RTTI if and only if polymorphic. Otherwise it does work too, without the need for RTTI (On Visual C++ at least).
As in: It does work with non polymorphic classes
I never said, and never assumed OP's class was polymorphic. I just added this piece of information to tell you that RTTI was not needed, unless using Polymorphism.

Edit: I guess using typeid by comparing strings is error prone. A better way (and I guess less error prone) would be this:



class C
{
...
}

C* someCPointer=new C;

...

if (typeid(*someCPointer)==typeid(C))
{
...
}


[edited by - Wildfire on July 2, 2003 10:19:09 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Wildfire
SabreMan: Please read my post properly. I said: RTTI if and only if polymorphic. Otherwise it does work too, without the need for RTTI (On Visual C++ at least).

Yes sorry, I misinterpreted that part of your post.
quote:

Edit: I guess using typeid by comparing strings is error prone. A better way (and I guess less error prone) would be this:

Either that, or dynamic_cast. I''d rather not speculate on what the solution should be without knowing more about the OP''s problem. The obvious question is why is it important to know the name of a class?

Share this post


Link to post
Share on other sites
You *could* just put a GetClassName() method on all your classes that returns the name you want. That doesn''t really help if using other people''s code though, and there''s most likely a better solution to whatever you decided you need to know the classname for.

Share this post


Link to post
Share on other sites
The problem that brought about this question is
i''m doing alittle MACRO stuff that creates two functions for you
(but looks like one)

Heres my code for my custom (and maybe crazy) callback stuff



//stores data for calling a class function from an object made with above macros

template<class R,class T> class CLASS_CALLBACK_DATA
{
public:

R (*callobjectfunction)(void*,T);
void *callobject;

R (*nonobjectcallfunction)(T);

//sets up and nothing callback

//calling after this will do nothing

CLASS_CALLBACK_DATA()
{
callobject=NULL;
callobjectfunction=NULL;
nonobjectcallfunction=NULL;
}

//creates the call data from a class object and class function

CLASS_CALLBACK_DATA(void *callobject,R (*callobjectfunction)(void*,T))
{
this->callobject=callobject;
this->callobjectfunction=callobjectfunction;
nonobjectcallfunction=NULL;
}
CLASS_CALLBACK_DATA(R (*callnonobjectfunction)(T))
{
callobject=NULL;
nonobjectcallfunction=callnonobjectfunction;
}

//calls the function

R call(T data)
{
if (callobject && callobjectfunction)
return callobjectfunction(callobject,data);
else
{
if (nonobjectcallfunction)
return nonobjectcallfunction(data);
}
return NULL;
}

bool isSet()
{
return (callobject && callobjectfunction) || (nonobjectcallfunction);
}

};
//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------



//class member callback help code

//only for functions with one void* parameter and any return type


//makes hopefully unused function name

#define COMPUTE_CALLBACK_FUNCTIONNAME(functionname) \
____CALLBACK__CALLBACKCALLBACK__##functionname

//use this before the code for a function that will have to be called back

//just fill in the parameters, as if making the prototype

#define CLASS_CALLBACK(returnvalue,classname,functionname,paramtype,paramname) \
returnvalue classname :: COMPUTE_CALLBACK_FUNCTIONNAME(##functionname) ( void *obj, paramtype paramname) \
{ \
return (( classname *) obj)->##functionname ( paramname ); \
} \
returnvalue classname :: functionname ( paramtype paramname )

//use this when declaring a function only inside a class definition

//that will be used for call back

//just fill in the parameters, as if making the prototype

#define CLASS_CALLBACK_H(returnvalue,functionname,paramtype,paramname) \
static returnvalue COMPUTE_CALLBACK_FUNCTIONNAME(##functionname) ( void *obj, paramtype paramname ); \
returnvalue functionname ( paramtype paramname );

//creates a CLASS_CALLBACK_DATA for the object and function that was made with the above macros

#define CLASS_CALLBACK_GET(object,returntype,classname,functionname,paramtype) \
CLASS_CALLBACK_DATA< returntype , paramtype >( object, classname :: COMPUTE_CALLBACK_FUNCTIONNAME( ##functionname ))




I would use CLASS_CALLBACK_H in a class defination to declaire the callback.

would use CLASS_CALLBACK when defining the callback function

would use CLASS_CALLBACK_GET to get the callback function

example of use


//in header

class MYCLASS
{
CLASS_CALLBACK_H(bool,MY_callback_func,int,the_int_name);

void call_callback();
};

//the source


CLASS_CALLBACK(bool,MYCLASS,MY_callback_func,int,the_int_name)
{
if (the_int_name>0)
return true;
else
return false;
}

void MYCLASS::call_callback()
{
CLASS_CALLBACK_GET(this,bool,MYCLASS,MY_callback_func,int).call(5);
}



Many times i find that my use of CLASS_CALLBACK_GET
occurs in the same class that the callback was made in
Of course this will not always be the case(and in that case you really do have to say what class to use)

basically i want

CLASS_CALLBACK_GET(object,returntype,classname,functionname,paramtype)

as

//for use in the same class as callback only
CLASS_CALLBACK_LESSTYPING_GET(object,returntype,functionname,paramtype)

=====================================================

I hope you can see that it isn''t extremely important that i know what it is.

ALSO,
about
quote:

The "type_info"-Class has a member-function
''const char* name() const'' which will give
you the class name.



i wasn''t looking for a string but actual preprocessor text replacement. But that looks useful for error logging purposes

Share this post


Link to post
Share on other sites
quote:

i wasn''t looking for a string but actual preprocessor text replacement. But that looks useful for error logging purposes



Actually, that''s the only case I''ve been using ''typeid'' for, so far. Since the output is read by a user, I''ve got no problem with compiler dependant differences in the name string (as long as it still somewhat resembles the classname).

Haven''t read through your all of your code yet, but I can''t quite make out what you''re trying to do from the text alone.

SabreMan & Petewood:
I see your points, and agree. I guess my opinion is a little one-sided, since we only use VC++ in the company I work for. I still blame MS for not mentioning that the string may vary . But as usual I speak before proper thinking =D

Share this post


Link to post
Share on other sites
Well just ignore what my problem is
because it must be my usual confusing self.

I just to know if there is a PREPROCESSOR way (there could not be another way) to get the class name that a current line is in

theidea: __LINE__ = 1,2,50,.......

__CLASSNAME__ = MYCLASS

a pointless example below:

class MYCLASS
{
void func()
{
//__CLASSNAME__ = MYCLASS

__CLASSNAME__::func();
}

};

can this exist without making my own compiler or modifing one

I didn''t think something like this existed and i am starting to believe it.

Share this post


Link to post
Share on other sites