A strange C++ class declaration - c++

Have read this thread in stackoverflow: Strange class declaration
, but still confused with below code in foo.h:
class Foo CHECKLEAKDCL {
I am sure that Foo should be the class name, since there are constructor and deconstructor which can imply this.
I cannot see any macro definition related with CHECKLEAKDCL in this .h file.
also I am confused with the answer for Strange class declaration , which saying that:
Q_CORE_EXPORT isn't an identifier. It's a platform-dependent macro,
and it's used to signal a class that's intended to be used across
library boundaries.
Can anyone give some more explanation of this?
UPDATE:
found this line in a .h file, which is included in foo.h:
#define CHECKLEAKDCL : private CheckLeak
so the class declarition should be :
class Foo : private CheckLeak {
So Foo is extending CheckLeak, right?

If you compile for windows (using Visual Studio), highly possible it will be evaluated to one of the Microsoft specific linkage identifiers, dllexport or dllimport :
https://msdn.microsoft.com/en-us/library/81h27t8c.aspx
It is used when you create a class which will be exported from a DLL or used from a DLL in an application, and dependig of this it's either evaluated to dllexport (DLL exporting the class) or dllimport (Application importing the class).
If you compile with GCC possibly it will evaluate to one of the gcc _-attribute__s. Such as __attribute__ ((visibility ("default"))) (https://gcc.gnu.org/wiki/Visibility)
These extensions to the core C++ are provided by compilers to make certain tasks more easily achievable (https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Extensions.html)
EDIT
After you updated the answer ... well, obviously you have a private inheritance from a class. But please note, this is a terrible macro you have there because
#define CHECKLEAKDCL : private CheckLeak
adds an : in your class declaration so you cannot use that symbol anymore to inherit from base classes.
I'd recommend that you get rid of that macro altogether, if you cannot, do not use it, it will confuse your code.

We cannot tell exactly what it is, as we have even less information than you do.
Normally, I have seen such macros resolve to export macro, for the library.
That is, the value of it should be defined as dllexport, dllimport or extern (depending on platform). When that is the case though, the macro appears before the class name.
Considering the macro appears after the class name, it can only resolve to a base class, or list of base classes, or an empty macro.
If you have the documentation, search for a base class that tracks or reports it's address to a memory tracker on construction and destruction.
Then, the code base should be compiled using a macrodefinition similar to this:
#define CHECKLEAKDCL() : private MemoryTrackingBaseClass
(where MemoryTrackingBaseClass is the class I mentioned above - according to your edit, CheckLeak).
If you want to simply compile, try using:
#define CHECKLEAKDCL()
Edit (addressing your update)
So Foo is extending CheckLeak, right?
Only when you want to check your application for leaks, using whatever CheckLeak implements.
In a production environment (after you use the definition inheriting from CheckLeak), you should probably define CHECKLEAKDCL as an empty macro (for speed).

As you've discovered, CHECKLEAKDCL is a macro that expands to the three tokens : private CheckLeak. Presumably CheckLeak is a class that adds some leak checking diagnostic behaviour to classes which inherit from it.
In general, this sort of obfuscation is not very helpful. Depending on the properties of CheckLeak, this macro might have unintended side effects, such as turning what appears to be a standard layout class into a non-standard layout class.
It would also be hard to add CHECKLEAKDCL to a class that wanted to inherit from another class for any other reason. (Are you supposed to class Foo CHECKLEAKDCL, public OtherBase ?)
Personally, if given the chance to improve this project I'd favour replacing this macro with its actual expansion in this case.

Related

Macro in class definition

class is defined using Macro. Not sure what is the significance of MACRO DEBUG_API here. [I understand #define is used to
turn on or off some specific set of code.] But below code I cannot grasp. any explanation would be appreciated
#define DEBUG_API
class DEBUG_API Cdebug
{
public:
/*
constructor, methods here.
*/
};
When defining this macro, you can choose attributes that will be applied to the class. These can be standard or compiler-specific attributes.
Your particular example is most probably an instance of the usual pattern for DLL headers under MSVC. Depending on a compile-time switch, DEBUG_API will be set to either :
__declspec(dllexport), which will make MSVC generate a .lib file containing the class' thunk; this is used when compiling the library as a DLL;
__declspec(dllimport), which will make MSVC link against the thunk generated above; this is used when linking with the DLL;
Nothing, which won't alter the behaviour of the class. This is used to link statically against the library.

Why does C++ has an additional class name declaration?

why do we have to declarer a class name in C++ like:
class MDT_DECL Transfer{
// declaration goes here
};
? What's the reason for the <DIRNAME>_DECL? I see it's especially used when the code needs to be compiled in Windows
You don't have to. But in windows you have to explicitly state you want the class to export symbols with _declspec(dllexport) (which is probably what that macro expands to).

In C++, how to use a singleton from a separate source file?

I'm trying to compile some other people's wrapper program on a large system, in which it's using a global object from another file, the definition of the class is like:
class __declspec(dllexport) A
{
...
static A * instance;
}
And in my separate source file (which I want to build to a .exe), I included the header file A.h, and declare at the beginning like this
A * A::instance;
to access the data in A.
The problem is, this piece of code can be built successfully on Linux, now when I try to build it in windows NT, it will have issues.
If I leave it like this, the compiler will complain with a C2491 error, definition of dllimport function not allowed.
If I remove this line of A declaration, I'll get a lot of error LNK2001: unresolved external symbol.
Not quite sure what is the problem here, I did some research online, but couldn't find a good answer, I myself is not that familiar with dll import/export and some C++ tricks either. Can some one provide some insights on the problem or which direction should I spend my time on to figure this out?
Or say, if I already have a static object like this, and I want to write another program to access it, how exactly should I do?
Please also correct me if I made any mistakes here. Thanks!
I think the keyword you need is extern, as in:
extern A *A::instance;
This says the variable A::instance is defined somewhere else, but you're telling the compiler about it so you can use it by name in this file.
__declspec(dllexport) is used when you want to export your function in a DLL. It should not be necessary as long as you're not calling the class from another DLL.
But I suspect your problem is related to using .c files and not the class specification. Try to read this by the way. It discusses dllexport in just-enough-detail Windows & C++: extern & __declspec(dllimport)
Singleton usually has a function, like
A::instance = NULL;
A * get_instance() {if (!A::instance) A::instance = new A; return A::instance;}
If you have a function like this you don't have to access A::instance directly.
And sorry, but what are you doing? Including a C++ header in a C program? Does it even compiles?
Personally I usually hide the instance in the .cpp file in an anonymous namespace. Then I provide a getInstance() function that returns a pointer or reference to it and I dllExport that function.
If you want to enforce things you can make the constructors for A private and make getInstance a friend.

What does it mean when a class declaration appears to have two names?

I'm trying to understand some C++ code which has the following class syntax:
class Q_MONKEY_EXPORT BasePlugin : public QObject
{
// some code comes here
};
I cannot understand the syntax class Q_MONKEY_EXPORT BasePlugin. To me it looks like if there are two names for the class. What exactly does this kind of syntax mean in C++?
Q_MONKEY_EXPORT is most likely a #define somewhere. Defines like that are sometimes required, for example when the class is in a library and needs to be exported when the header file is included from somewhere else. In that case, the define resolves to something like __declspec(dllexport) (the exact syntax will depend on the tools you are using).
That's most probably a preprocessor directive telling the compiler the symbol is to be exported.
It's probably defined as:
#define Q_MONKEY_EXPORT _declspec(dllexport)
which will cause your class to be exported to the dll.
The full declaration will be expanded, before compilation, to:
class _declspec(dllimport) BasePlugin : public QObject
{
// some code comes here
};
EDIT:
As David Heffernan pointed out, macros like these are generally used to let the compiler know whether it needs to import or export the symbols. Usually defined as dllimport for outside modules and dllexport when building the module. I doubt that's the case here, since the name suggests exporting, but it's best to check the documentation or actually go to the definition.
Q_MONKEY_EXPORT is a macro (all upper case is convention for macro) that typically resolves to something like __declspec(dllexport) when you are building the DLL and resolves to __declspec(dllimport) when you are using the DLL.
You can find out exactly what it is by reading your include files.

How to work (portably) with C++ class hierarchies & dynamic linked libraries

Ok, so I know portability is not the strong point of C++, but I have to get my code running on both Mac&Windows. I've come up with a solution, but it's not perfect, and I'm interested to see if there is someone out there who can suggest a better one.
I need to us a class hierarchy in several DLLs/bundles - e.g., I have an abstract base class BaseClass; and I scan a given directory for DLLs, and for each DLL, I look for the factory method BaseClass* CreateObject(); - which returns a "BaseClass". I have a "shared header file" that I include both in the "main executable" & in the DLLs, that declares the BaseClass like this
#ifdef _MAC
#define DECLSPEC
#else
#ifdef COMPILING_DLL
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
#endif
class DECLSPEC BaseClass{
[.. base "interface" declaration .. ]
}
And then, in my DLL, I would typically include the BaseClass declaration, and declare my own "concrete" class:
class MyDllClass:public BaseClass{
[.. actual DLL class definition/implementation here goes here ...]
}
So far, so good. Now for some reason, I need to differentiate in my main executable between two different kinds of BaseObjects - say I have a DescriptionClass and an ActionClass, both of which are BaseClass, but have a slightly different interface. My fist implementation was to simply do modify the "shared header" and add:
class DECLSPEC DescriptionClass{
[.. base "Description interface" declaration .. ]
}
class DECLSPEC ActionClass{
[.. base "Action interface" declaration .. ]
}
Then my DLL would become:
class MyDllClass:public ActionClass /* or DescriptionClass, depending on case*/ {
[.. actual DLL class definition/implementation here goes here ...]
}
And in my main executable, I would use it like this:
BaseClass* obj = CreateObjectFromDLL("path_to_dll");
ActionClass* action_obj = dynamic_cast<ActionClass*>(obj);
if(action_obj){
// Do the stuff that is relevant for Action objects
}
DescriptionClass* description_obj = dynamic_cast<ActionClass*>(obj);
if(description_obj){
// Do the stuff that is relevant for Description objects
}
And herein lies the problem: although it works on Windows with Visual Studio (probably due to the MS declspec extension), it fails on Mac (not sure now if it fails on Debug, but I'm sure it fails on release) when compiled with GCC. The reason is simple, even if not immediately obvious: the executable & the dynamic library are compiled separately. Although they both include the declaration of BaseClass, ActionClass, DescriptionClass - these classes are not the same, they are just "identical copies" that are present in the binary and the DLL. So actually, what I'm creating in the DLL is a dll'BaseClass* , which happens to have the same memory layout with main'Baseclass*, so the pointers are compatible, so when I pass the pointer from DLL to EXE, it all works "as expected". OTOH, when I go to a more complex class hierarchy, the vtables/RTTI of dll'ActionClass and main'ActionClass are no longer identical (although in source code they are identical), so when I try do convert (through dynamic_cast) a main'BaseClass* to a main'ActionClass* i get a null result -> because my pointer actually points to a dll'BaseClass object / dll'ActionClass object, and alghough in the DLL I can convert with no proble a "BaseClass*" into a "ActionClass*" - in the main executable, I can't convert the dll's "BaseClass*" into a "ActionClass*", due to the subtle runtime differences between the DLL's and the "main executable's" version of Action Class.
I've "fixed" this by declaring a virtual method in the BaseClass (something like "bool isActionClass()" ), so now I can differentiate... but I'm not very happy with this solution.
Is there something for GCC - e.g. some declaration similar to "__declspec" - a way to guarantee that the same class declared in "main executable" and in "dll" will be 100% compatible?
I actually found the answer to my question due to the fact that I needed to formulate it completely, and I did a better google search :)
It seems to be
__attribute__((dllimport)) // import
__attribute__((dllexport)) // export
Will try that, I thought I'd leave the question here too, in case someone else stumbles on this problem (and as a warning to people that same header file included in a "main binary" & DLL will normaly lead to different actual implementation, depending on the compiler options - unless you put the proper dllimport/export attributes on the class).
That would only work if RTTI is enabled. You, probably, get that automatically enabled in MSVC++, but gcc requires specific link switches. Look in GCC FAQ for details.