By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,889 Members | 1,297 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,889 IT Pros & Developers. It's quick & easy.

use base class constructors always

P: n/a
hi,
In the following code, I would like not to have to declare the
constructors in bar ( either the default or the (int a) constructor ).
When I remove them, bar has no idea of construction with an int, so I
get compile errors. I currently have to declare them for every class
inheriting foo, and it would be much nicer just with the init. Is there
a nice way of doing this? I am currently using a
macro, like CONSTRUCTOR(bar) which feels a bit squiffy to me.
Also, if I'm not pushing my luck I would like some way to make the init
pure virtual to force implementation in inheritors, without getting the
linker error for foo::init that I get when I try.
thanks,
iain

class foo
{
public:
foo() {}
foo( int a ) {init(a);}
virtual void init ( int a ) {};
};

class bar: public foo
{
public:
bar() {}
bar( int a ):foo(a) {}
virtual void init( int a ){/*etc.*/}
};

void main()
{
bar a( 1 );
bar b;
b.init( 2 );
}

Jul 23 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
pixelbeast wrote:
In the following code, I would like not to have to declare the
constructors in bar ( either the default or the (int a) constructor ).
When I remove them, bar has no idea of construction with an int, so I
get compile errors.
Post the code which gives you the compile errors, don't post speculation.
I currently have to declare them for every class
inheriting foo, and it would be much nicer just with the init.
'init' is a deceitful name. True initialisation happens during object's
construction. If you don't want to initialise during construction, it's
your right, but your base class object ('foo' part of any derived class)
will be initialised (or at least attempted at initialising) when the
derived class object is constructed, not when 'init' is called.
Is there
a nice way of doing this?
A nice way of doing what, exactly?
I am currently using a
macro, like CONSTRUCTOR(bar) which feels a bit squiffy to me.
Where? I don't see any 'CONSTRUCTOR' macro in the code posted.
Also, if I'm not pushing my luck I would like some way to make the init
pure virtual to force implementation in inheritors, without getting the
linker error for foo::init that I get when I try.
Again, what linker errors? Post the code that produces the errors.
thanks,
iain

class foo
{
public:
foo() {}
foo( int a ) {init(a);}
Here the 'init' of the class 'foo' will be called, not the 'init' of
the most derived class (as you might hope).
virtual void init ( int a ) {};
};

class bar: public foo
{
public:
bar() {}
bar( int a ):foo(a) {}
virtual void init( int a ){/*etc.*/}
};

void main()
There is no 'void main' in C++, BTW.
{
bar a( 1 );
bar b;
b.init( 2 );
}

V
Jul 23 '05 #2

P: n/a
i think you are right ofcourse, I need to re-evaluate this, the
splitting of constructors and inits was done a long time ago in my
codebase, but looking at the current situation, and the problems it is
causing, I will go back and investigate why I did it.

for completeness, you requested code that causes the compile errors,
The following code (removing the constructors from bar)....

class foo
{
public:
foo() {}
foo( int a ) {init(a);}
virtual void init ( int a ) {};
};

class bar: public foo
{
public:
//comment bar() {}
//comment bar( int a ):foo(a) {}
virtual void init( int a ){}
};

void main()
{
bar a( 1 );
bar b;
b.init( 2 );
}

... gives the following error..
d:\dev\test\test\t.cpp(20) : error C2664: 'bar::bar(const bar &)' :
cannot convert parameter 1 from 'int' to 'const bar &'
Reason: cannot convert from 'int' to 'const bar'
No constructor could take the source type, or constructor
overload resolution was ambiguous

... and trying to make "init" pure virtual as follows...

class foo
{
public:
foo() {}
foo( int a ) {init(a);}
virtual void init ( int a ) =0;
};

class bar: public foo
{
public:
bar() {}
bar( int a ):foo(a) {}
virtual void init( int a ){}
};

void main()
{
bar a( 1 );
bar b;
b.init( 2 );
}

... gives the following linker error...
t.obj : error LNK2019: unresolved external symbol "public: virtual void
__thiscall foo::init(int)" (?init@foo@@UAEXH@Z) referenced in function
"public: __thiscall foo::foo(int)" (??0foo@@QAE@H@Z)
Debug/test.exe : fatal error LNK1120: 1 unresolved externals

.... finally the macro i was attempting to use, was equivalent to the
one used in following, where I was testing your analysis of my init...
#define CONSTRUCTORS(_name) \
_name() {} \
_name(int a) : foo(a) {}

class foo
{
public:
foo() {}
foo( int a ) {init(a);}
virtual void init ( int a ) {};
};

class bar: public foo
{
public:
CONSTRUCTORS(bar)
virtual void init( int a ){ val = a;}
int val;
};

void main()
{
bar a( 1 );
bar b;
b.init( 2 );

bar c(3); // doesn't work - as Victor predicted.
// virtual init in foo is called
bar d;
d.init(3);

bar e;
foo *pe = &e;
pe->init(3);
}
.... however, as is obvious - my splitting of contructor
responsibilities is producing problems where there shouldn't be any and
I shall be changing it .

Thanks for being frank, sorry about the void main();

Jul 23 '05 #3

P: n/a
pixelbeast wrote:
i think you are right ofcourse, I need to re-evaluate this, the
splitting of constructors and inits was done a long time ago in my
codebase, but looking at the current situation, and the problems it is
causing, I will go back and investigate why I did it.

for completeness, you requested code that causes the compile errors,
The following code (removing the constructors from bar)....

class foo
{
public:
foo() {}
foo( int a ) {init(a);}
virtual void init ( int a ) {};
};

class bar: public foo
{
public:
//comment bar() {}
//comment bar( int a ):foo(a) {}
virtual void init( int a ){}
};

void main()
{
bar a( 1 );
bar b;
b.init( 2 );
}

.. gives the following error..
d:\dev\test\test\t.cpp(20) : error C2664: 'bar::bar(const bar &)' :
cannot convert parameter 1 from 'int' to 'const bar &'
Reason: cannot convert from 'int' to 'const bar'
No constructor could take the source type, or constructor
overload resolution was ambiguous
What else to expect? You haven't defined a constructor in the 'bar'
class which would accept an argument of type 'int', how should the
compiler know what you want to do when you write

bar a( 1 );

??? Remember, constructors are *not* inherited.
.. and trying to make "init" pure virtual as follows...

class foo
{
public:
foo() {}
foo( int a ) {init(a);}
Again, this would call 'foo::init', which is pure, and you'll have
undefined behaviour.
virtual void init ( int a ) =0;
};

class bar: public foo
{
public:
bar() {}
bar( int a ):foo(a) {}
virtual void init( int a ){}
};

void main()
{
bar a( 1 );
bar b;
b.init( 2 );
}

[...]

... however, as is obvious - my splitting of contructor
responsibilities is producing problems where there shouldn't be any and
I shall be changing it .

Thanks for being frank, sorry about the void main();


Don't be sorry, just get rid of it. C++ has no 'void main'...

V
Jul 23 '05 #4

P: n/a
pixelbeast wrote:
hi,
In the following code, I would like not to have to declare the
constructors in bar ( either the default or the (int a)
constructor ). When I remove them, bar has no idea of
construction with an int, so I get compile errors. I
currently have to declare them for every class inheriting
foo, and it would be much nicer just with the init. Is there
a nice way of doing this?
Unfortunately, no. I believe that the standards committee is
looking at ways of adding this to future versions of the
language.
class foo
{
public:
foo() {}
foo( int a ) {init(a);}
virtual void init ( int a ) {};
};

class bar: public foo
{
public:
bar() {}
bar( int a ):foo(a) {}
virtual void init( int a ){/*etc.*/}
};


Something you might not be aware of: when you construct
a bar from an int, eg:

bar b(1);

then it will call foo::init, and bar::init will never be
called. The virtual function mechanism doesn't kick in
until after the object has been constructed. In other
words, the call to 'init' in foo(int) does not try to
call init in any derived classes, because the derived
object has not yet been constructed.

Jul 23 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.