Recycle Constructors ... ?

Recycle Constructors ... ?


Is it possible to use a constructor in another constructor of the same class (in Java it is) ?

I tried the following but the compiler complains: 'Test' is not an unambiguous base class of 'Test'

I don't linke to rewrite the init stuff several times ...

    class Test {
        int i; char c;
      public:
        Test(int _i) { i = _i; /* init stuff */ }
        Test(int _i, char _c) : Test(_i) { c = _c; } // WRONG !!
    };




Is it possible to use an inherited constructor without overwriting it ?

    class A {
        string text;
      public:
        A(string _text) text(_text) { /* init stuff */ }
    };
   
    class B : public A {
      public
        print() { std::cout << text}
    };
   
    /* ... */
   
    B obj = B("Hello World");
    B.print();
   



 - Many thanks for all the other answers I got so far ...

             Ingo





.
bormuthAsked:
Who is Participating?
 
nietodConnect With a Mentor Commented:
>> Is it possible to use a constructor in
>> another constructor of the same class
In a word--"no".

In C++ you cannot dirrectly call a constructor for a class.  The constructor may only be called by the compiler, as part of object creation.  There are ways to cause the constructor to be called, but there is no way to call it directly.  

>> I don't linke to rewrite the init
>> stuff several times ...
Often you can get away with writting a non-constructor, initialization procedure and then call this procedure from multiple constructors.  However this may be less efficient than performing the initialization directly in the constructor.  More importantly, it usually will not work to initialize members that must be constructed using a non-default constructor or to initialize constant, non-static members.

continues
0
 
nietodCommented:
>> Is it possible to use an inherited
>> constructor without overwriting it ?
Constructors are never inherited.  So in your example, B does not have a constructor that takes a string parameter, so the line

 B obj = B("Hello World");

will cause a compiler error.

But you can make a derived class's constructor initialize the base class by explicitly using one of the the base class's constructors.  For example

class B : public A {
public:
    B(string _text) : // Note you forgot this colon in your sample.
      A(_text) // Invoke the base class constructor.
      {
        /* init stuff */
      }
   print() { std::cout << text}
};
0
 
DanRollinsCommented:
In the ctor for the derived class, just add a ctor that initializes the base class:

   <derived>(<args> : <base>( <args> ) {};

class A
{
public:
    A()            { m_s[0]=0; }    
    A( LPCSTR sz ) { strcpy(m_s, sz); }    
    char m_s[100];
};
class B : public A
{
public:
    B( LPCSTR sz ) : A( sz ) {};  // <<<< here
    B( int n ) { sprintf(m_s,"%d",n); }    
};


   A a("hi there");
   B b("hi there");
   B b2(123);
   cout << b.m_s;  // "hi there"
   cout << b2.m_s; // "123"

-- Dan
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
DanRollinsCommented:
Dang, I'm just not quick enough with the Answer button.

-- Dan
0
 
nietodCommented:
But why on earth would you take an example that uses safe techniques, like string objects and stream objects and replace them with flawed techniques, like NUL terminated character arrays and C streams?  You don't want to suggest that those changes should be made, right!?
0
 
bormuthAuthor Commented:


1)

So, when I have const members ther is no way that prevents me from writing multible constructions ?

2)

The thing is I want to built a complex, abstract template class A with multible constructers.

The user has do derive his class from A and only add one virtual function to make it not abstract. In this user-function he can use const members of A. I don't want to make him redeclare all the constructors (this would be a bit complicated).

Is there realy no way to prevent this ?

0
 
DanRollinsCommented:
>>But why on earth would you take an example...and replace ...
 
Don't flatter yourself... I did not copy your example (check the timing of the posts--I did not even see it)  My clearly-written example illustrates the basic concept using simple, easily-recognized code.  Some error-checking was omitted for clarity.  Sheesh.

-- Dan
0
 
nietodCommented:
>> So, when I have const members ther is no
>> way that prevents me from writing multible
>> constructions ?
No you cna have multiple constructors.  You can't have those constructors call a single shared initialization procedure.  (Actually they can, but that procedure can't initialize the constant members.  The constant members must be initialized in the initialization section of each constructor.

>> I don't want to make him redeclare all
>> the constructors (this would be a bit
>> complicated).
constructors are never inherited.  A derived class must declare any constructors it needs.  If the derived class wants constructors that exactly mirror the base class constructors, it needs to define them.  Or the derived class can have unque constructors if it wants.  it may define only one constructor that mirrors a base class constructor it it might define constructors that don't mirror the base class ones at all.  

(This of course does not apply to the automatically generated constructors, the copy constructor and default constructor.  You don't have to define these, if you don't want, and they will be defined for you, if possible, but still they are not inherited.)

>> I did not copy your example
But he sample provided in the question uses string objects and C++ I/O.  You altered this to use dangerious techniques.  You could inadvertadtly convince a client to remove these tecyhniques in favour of poor techniques.

>> Some error-checking was omitted for clarity.
Error checking?  Its impossible to check for errors with printf()!  And error checking is practically useless with NUL-terminated character arrays.  usually the best you can do is to print out some sort of error message and kill the program.  Its better to write code that works reliably instead.  That is what the orignal program did.
0
 
jasonclarkeCommented:
> So, when I have const members ther is no way that
> prevents me from writing multible constructions ?

You are correct...unless they can be static, (which for constants they often can be).


> In this user-function he can use const members of A.
> I don't want to make him redeclare all the constructors

In the derived class why should he have to?  He only needs to call the constructors of A that he needs.

Sometimes, const data members are more trouble than they are worth (in complex situations) - it is often better to leave them non physically const, but private and allow access via const methods - which is probably a more general way of doing it anyway.
0
 
jasonclarkeCommented:
> My clearly-written example illustrates the basic concept > using simple, easily-recognized code.

just using gratuitously bad code...

I suppose that we must accept your view point, however, since you clearly must be writing your comments using punched cards or perhaps some sort of teletype.  Innovation and progress in computer science are clearly things which hold no value for you... ;-)
0
 
DanRollinsCommented:
>>?  Its impossible to check for errors with printf()!  
Describe *any* way that this could fail:

  char m_s[100];
  B( int n ) { sprintf(m_s,"%d",n); }  


>> ... That is what the orignal program did.  
You still insist that I copied your code. lol.  Your example does not even compile!  Something about string and std::

-- Dan
0
 
jasonclarkeCommented:
> Describe *any* way that this could fail:

it is not robust under changes - array bounds come into play - and of course it is very wasteful of memory (100 bytes is excessive).

And, I see you conveniently didn't ask the same question of your base class constructor...
0
 
DanRollinsCommented:
>>see you conveniently didn't ask the same question of your base class constructor...
 
Didn't need to.  Addition of simple, but unnecessarily obfuscating error checking eliminates the problem:

   A( LPCSTR sz ) { strncpy(m_s, sz, sizeof(m_s) ); }    

-- Dan
0
 
jasonclarkeCommented:
But how can it be as simple as:

std::string m_s;

A(const std::string& s) : m_s(s) {}
   
This is all rather pointless, however, since you seem to be happy using C++ as a kind of C with extra stuff.  However, perhaps you could consider this (I may have mentioned this before) - imagine writing this program (one of the simplest possible) - equivalently - in C:

#include <iostream>
#include <string>

int main()
{
   using namespace std;

   cout << "Please enter your first name\n";
   string name;
   cin >> name;
   cout << "Hello " << name << "\n";
}

Look for the answer in this article by Bjarne Stroustrup about learning C++: http://www.research.att.com/~bs/new_learning.pdf

You might learn something...but somehow I don't think it will matter to you...
0
 
nietodCommented:
>> Sometimes, const data members are more trouble
>> than they are worth (in complex situations) - it
>> is often better to leave them non physically const,
>> but private and allow access via const methods -
>> which is probably a more general way of doing it
>> anyway.
And they are also often used incorrectly.  They are often used for values that are supposed to be constant for an entire class (all objects in a class, not for 1 object of a class.)  So what is often required is a static or constant static member, not a non-static constant member.  

>> Describe *any* way that this could fail:
Have you ever had a bug in one of your programs.  If not, then what you've written is fine.  If you ever make mistakes, then this code is a good opportunity for you to make mistakes that the compiler will not catch for you.  I'm not perfect, so I don't take chances.  

>> and of course it is very wasteful of
>> memory (100 bytes is excessive).
And for all that waste it is inadqeuite.  What if you need a string of 200 characters?  What about 300?  10,000?  And it is inneficient.  if the objects must be copied all that string data must be copied too.

>> Addition of simple, but unnecessarily
>> obfuscating error checking eliminates
>> the problem:
It doesn't iliminate any errors.  At best it might prevent a crash and cause unpredictable behavior instead that will be hard to track down.  What if you try to pass a string that is longer than 100 charcters?  Well you will loose information.  This goes on quitely.  The program ceases to run correctly, but there is never a clear indication of this.  That is aserious problem.  Why invite such a problem when you don't have to?

More importantly.  you don't seem to understand how strncpy works.  That is the wrong way to use it.  That code will potentially leave the string unterminated.  That as an opporunity for a different crash.  ie. you replaced one crash with a different one.  

If NUL termianted character arrays are so easy to work with, why did you make this mistake?  Maybe you aren't perfect either.  You could write code that allows the compiler to make up for your imperfections...
0
 
DanRollinsCommented:
You are both correct.  printf and sprintf and StrNCpy are unsafe and just possibly, the downfall of civilization as we know it. sprintf(m_s,"%d",n) fails inside the Event Horizon of massive black holes. cin >> name is a useful technique for getting input of a person's name.  Bjarne Stroustrup walks and talks with God.  

The discussion of char arrays and their initialization and the use of printf is entirely irrelevant to this question. To avoid further discord, I would like to amend my example:

class A {
public:
   A()        { m_n= 0; }    
   A( int n ) { m_n= n; }    
   int m_n;
};
class B : public A {
public:
   B( int n ) : A( n ) {};  // <<<< here
};

-- Dan
0
 
jasonclarkeCommented:
> Bjarne Stroustrup walks and talks with God.  

I don't believe I have met anybody so unwilling to consider an argument.  I just thought, that since you clearly give no weight to either my or nietod's credentials as C++ programmers, then maybe just maybe somebody a little more well known would maybe sow a seed or two of doubt in your mind.  It seems, however, that not even Bjarne Stroustrup matches your standard.
0
 
nietodCommented:
>>  printf and sprintf and StrNCpy are unsaf
You've demonstrated how they can be used incorrectly.

Your code will cause terrible problems when passed a string  that is longer than 99 characters.  Even in a short simple example like this where you try to demonstrate how to use them safely you make mistakes in which they are unsafe to use.  
0
All Courses

From novice to tech pro — start learning today.