Solved

Recycle Constructors ... ?

Posted on 2001-08-26
18
478 Views
Last Modified: 2012-06-21
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





.
0
Comment
Question by:bormuth
  • 6
  • 6
  • 5
  • +1
18 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
Comment Utility
>> 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
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> 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
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
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
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Dang, I'm just not quick enough with the Answer button.

-- Dan
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
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
 

Author Comment

by:bormuth
Comment Utility


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
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
>>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
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> 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
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
> 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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
> 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
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
>>?  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
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
> 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
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
>>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
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
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
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>> 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
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
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
 
LVL 9

Expert Comment

by:jasonclarke
Comment Utility
> 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
 
LVL 22

Expert Comment

by:nietod
Comment Utility
>>  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

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now