Re: Undefined reference to...
On Nov 10, 8:27 pm, "Alf P. Steinbach /Usenet"
<alf.p.steinbach+use...@gmail.com> wrote:
* Andrea Crotti, on 10.11.2010 19:08:
[...]
Anyway I rephrase, first question is why this below doesn't find the
reference to the vtable?
class Base
{
public:
virtual void printOut();
};
class Extended : public Base
{
public:
void printOut() { cout<< "hello"; }
};
The only subclass actually implements the method I want, so
should not that be enough? Or maybe it complains because
the vtable is constructed at runtime (giving the possibility
of bad crashes if nothing is found)?
The compiler doesn't know that you're not creating any pure
Base instances.
Also, during the constructor and destructor of Base, the dynamic
type is Base, and any calls to the virtual function go to
Base::printOut.
And it doesn't care.
A virtual member function, except a pure virtual member
(that's a one with "= 0" at the end) must have an
implementation, so that the compiler can very mechanically put
the address of that implementation in the vtable, or use it in
whatever scheme it uses as an alternative to vtables.
Yes. And if the dynamic resolution results in a call to a pure
virtual function (e.g. because the call is made while in the
constructor of Base), the behavior is undefined. Generally, the
compiler will generate code which will cause the program to
crash with an error message (although IIRC, early versions of
g++ didn't have the error message, and some versions of VC++ do
something else, and don't even crash).
The second question was if it was possible to do something like
class Extended;
class Base
{
public:
virtual void printOut() = 0;
static Base getLower() {
Extended e;
return e;
}
};
class Extended : public Base
{
public:
void printOut() { cout<< "hello"; }
};
Apparently not if I understand, then I'll find some other ways..
Problems with the above include
* 'getLower' attempts to return an object of abstract class.
* A local variable is declared with incomplete type 'Extended'.
* If those obstacles weren't in the way, 'getLower' would perform
a *slicing*, returning only the Base part of 'e', and then of type
'Base'.
It's not clear what you're attempting, but it may be that you
want a Meyers' singleton:
class Base
{
public:
virtual void printOut() = 0;
static Base& getLower();
};
class Extended: public Base
{
public:
void printOut() { cout << "hello"; }
};
Base& Base::getLower()
{
static Extended e;
// Whatever code you were intending to have here, then:
return e;
}
Note that with this scheme you always get the same object --
a singleton -- from 'getLower'.
Just for the record, that's *not* a Meyers' singleton, or any
other type of singleton. (The first condition to be a singleton
is that there is no way of getting more than one instance. In
a Meyers' singleton, this is done by making the object
noncopyable, and the constructor private. Which, of course,
excludes derivation, unless you make the derived class
a friend.)
However, what you've just shown *is* the closest working
approximation of what he seems to be trying to do. Unless he
actually wants more than one instance---it's not really clear.
For more than one instance, he'd need a factory function, e.g.
class Base
{
public:
virtual void printOut() = 0;
static std::auto_ptr<Base> getLower();
};
class Extended: public Base
{
public:
void printOut() { cout << "hello"; }
};
std::auto_ptr<Base> Base::getLower()
{
return std::auto_ptr<Base>( new Extended );
}
--
James Kanze