use base class constructors always

P

pixelbeast

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 );
}
 
V

Victor Bazarov

pixelbeast said:
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
 
P

pixelbeast

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();
 
V

Victor Bazarov

pixelbeast said:
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
 
O

Old Wolf

pixelbeast said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top