Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a special way to declare/define C++ constructors (and destructors)

EDIT: This is a discussion about best practice in the (simplified) case presented below. Whatever tool, coding style or something else you want to suggest, post it. Thanks.

Why are there no special ways to declare or define ctors/dtors without duplicating the name of the class? It's annoying, especially when prototyping and ending up changing the name of the class a lot.

What I mean is something with typedef like this:

struct SomeClassThatDoesSomething {
    typedef SomeClassThatDoesSomething ThisClass;
    ThisClass() { PrepareToDie(); }
    ThisClass(int a) : _a(a) { PrepareToDie(); }
    ThisClass(float a, int b) : _b(a), _a(b) { PrepareToDie(); }
    ThisClass(float a, char * b) : _b(a), _c(b) { PrepareToDie(); }
    ThisClass(char * a, int b) : _c(a), _a(b) { PrepareToDie(); }
    ThisClass(ThisClass &rhs) {  }
    ~ThisClass() {}
    void Burn() {}
    void PrepareToDie() {}
    int _a;
    float _b;
    char *_c;
};

struct SomeDerivedClassThatDoesSomething : public SomeClassThatDoesSomething {
    typedef ThisClass BaseClass;
    typedef SomeDerivedClassThatDoesSomething ThisClass;
    ThisClass(BaseClass &is_not_amused) : BaseClass(is_not_amused) { BaseClass::_a = 1; PrepareToDie(); }
    ThisClass(float a, char * b) : BaseClass(b, a) {}
    ~ThisClass() { BaseClass::Burn(); }
    unsigned int _a; // Different semantics up the tree.
};

//EDIT: Consider this: Enforce export name decoration policy.
#define DLL_API __declspec(dllexport) 
// ... or dllimport - not the point here
#define def_export_struct( name ) struct C##name; typedef C##name *P##name; struct DLL_API C##name 

def_export_struct( SomeOtherClassThatDoesSomething ) : public SomeDerivedClassThatDoesSomething 
{
//...
};
namespace mass_destruction {
    def_export_struct( Int )
    {
    //... (The point is that search and replace gets very unreliable in big projects)
    }
};

It only works for ctors and only on MSVC; I've been using it and, although not a big feature, it makes life easier. This is a trivial example, but imagine a fairly complicated structure. (A handy side-effect is also that you have an alias in class without having to track its name.) Am I missing something? Am I really the only one who needs this? The point is not whether it compiles, the point is that I've got it partly working all over the place for me and it does wonders. Until I hit the standard... (This is not a compliance discussion.)

like image 927
ActiveTrayPrntrTagDataStrDrvr Avatar asked Feb 29 '12 14:02

ActiveTrayPrntrTagDataStrDrvr


People also ask

Which is the correct way to define destructors?

A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ).

Is it correct to define destructor without defining constructor?

Yes, the destructor is nothing more than a function. You can call it at any time. However, calling it without a matching constructor is a bad idea.

What are the rules which has to followed while writing constructors and destructors?

The following restrictions apply to constructors and destructors: Constructors and destructors do not have return types nor can they return values. References and pointers cannot be used on constructors and destructors because their addresses cannot be taken. Constructors cannot be declared with the keyword virtual .

What is constructor and destructor define with a program?

Constructor and Destructor are the special member functions of the class which are created by the C++ compiler or can be defined by the user. Constructor is used to initialize the object of the class while destructor is called by the compiler when the object is destroyed.


2 Answers

Ever heard of search-and-replace?

I guess that most people either use ex, vim, sed. etc: s/search/replace/g or equivalent to change the name of their classes, or don't change them that often to be upset by the lack of this feature.

You could use a #define to do this compliantly:

#define THIS_CLASS MyLongClassNameThatIChangeLotsAndLots
class THIS_CLASS{
    THIS_CLASS() { PrepareToDie(); }
    THIS_CLASS(int a) : _a(a) { PrepareToDie(); }
    THIS_CLASS(float a, int b) : _b(a), _a(b) { PrepareToDie(); }
    THIS_CLASS(float a, char * b) : _b(a), _c(b) { PrepareToDie(); }
    THIS_CLASS(char * a, int b) : _c(a), _a(b) { PrepareToDie(); }
    THIS_CLASS(THIS_CLASS &rhs) {  }
    ~THIS_CLASS() {}
};
#undef THIS_CLASS

What is upsetting, I'll agree, is the lack of a standard way to refer to the base class(es) of a type -- I normally privately typedef ... base_t in classes, then use that for initialiser lists, etc.

like image 69
James Avatar answered Nov 11 '22 14:11

James


If your class names are getting frustratingly long-winded, consider making more use of namespace.

namespace, combined with using is great for making your typenames only as verbose as each context demands.

namespace Something
{
  struct Derived : public SomeClass
  {
     Derived() {...etc.}

  }
}
like image 31
Drew Dormann Avatar answered Nov 11 '22 12:11

Drew Dormann