473,320 Members | 1,794 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Why can't I do this?

Dear Gurus,

This is a fairly simple question, but I can't figure out what the answer is.
I can easily change my code, but I want to know why I can't do this to
further my knowledge of the C++ language (and OO):

class a
{
public:
a(){ vm(); }
virtual void vm() = 0;
};

class b : public a
{
public:
void vm() { }
};

int main()
{
b B;

return 0;
}

VC++ says: "error LNK2001: unresolved external symbol "public: virtual void
__thiscall a::vm(void)"

I understand that 'a' doesn't have a implementation of 'vm', but also I
cannot create an instance of 'a' either (because it has a pure virtual
function) so when I create a 'b' why can't 'a's constructor call 'b's 'vm'?

Quentin.
Jul 19 '05 #1
14 2279
On Wed, 17 Sep 2003 22:46:09 GMT, "Quentin" <IH*******@SpamSux.com> wrote:
This is a fairly simple question, but I can't figure out what the answer is.
I can easily change my code, but I want to know why I can't do this to
further my knowledge of the C++ language (and OO):

class a
{
public:
a(){ vm(); }
virtual void vm() = 0;
};

class b : public a
{
public:
void vm() { }
};

int main()
{
b B;

return 0;
}

VC++ says: "error LNK2001: unresolved external symbol "public: virtual void
__thiscall a::vm(void)"

I understand that 'a' doesn't have a implementation of 'vm', but also I
cannot create an instance of 'a' either (because it has a pure virtual
function) so when I create a 'b' why can't 'a's constructor call 'b's 'vm'?


This is a FAQ.

Look it up in the FAQ.

If necessary, first look up where the FAQ is (Google, this group).
Hth.,

- Alf

Jul 19 '05 #2
> Look it up in the FAQ.

Thanks Alf!

Quentin.
Jul 19 '05 #3
"Quentin" <IH*******@SpamSux.com> wrote in message
news:Ru*********************@news1.calgary.shaw.ca ...
Dear Gurus,

This is a fairly simple question, but I can't figure out what the answer is. I can easily change my code, but I want to know why I can't do this to
further my knowledge of the C++ language (and OO):

class a
{
public:
a(){ vm(); }
virtual void vm() = 0;
};

class b : public a
{
public:
void vm() { }
};

int main()
{
b B;

return 0;
}

VC++ says: "error LNK2001: unresolved external symbol "public: virtual void __thiscall a::vm(void)"

I understand that 'a' doesn't have a implementation of 'vm', but also I
cannot create an instance of 'a' either (because it has a pure virtual
function) so when I create a 'b' why can't 'a's constructor call 'b's 'vm'?
Quentin.


Because at the time of construction of A part "this" pointer is still of
type A, hence it does not know anything about B yet. In other words,
construction starts at the top of inheritance tree, and the type of this
pointer follows. BTW, Mayers in his book Effectife C++ has a chapter about
this... you shouldn't (in most cases) call virtual functions from
constructors.

Martin
Jul 19 '05 #4
"Quentin" <IH*******@SpamSux.com> wrote in message
news:Ru*********************@news1.calgary.shaw.ca ...
Dear Gurus,

This is a fairly simple question, but I can't figure out what the answer is. I can easily change my code, but I want to know why I can't do this to
further my knowledge of the C++ language (and OO):

class a
{
public:
a(){ vm(); }
virtual void vm() = 0;
};

class b : public a
{
public:
void vm() { }
};

int main()
{
b B;

return 0;
}

VC++ says: "error LNK2001: unresolved external symbol "public: virtual void __thiscall a::vm(void)"

I understand that 'a' doesn't have a implementation of 'vm', but also I
cannot create an instance of 'a' either (because it has a pure virtual
function) so when I create a 'b' why can't 'a's constructor call 'b's 'vm'?
Quentin.

I'm by no means a guru, and of course you can check the FAQ, but I believe
this is the problem:
Class A is an abstract base class containing an unimplemented virtual
function. Therefore, you cannot call vm() from the Class A constructor,
because in Class A it doesn't exist.

Call vm() from Class B's constructor.

Think about it... why should the compiler allow you to call Class A's vm()
if it has no function body? The compiler is doing you a favor here.

An additional question: were you to derive additional classes from A, how
would the compiler know which instance of vm() to call in A's constructor?

Jul 19 '05 #5

"Quentin" <IH*******@SpamSux.com> wrote in message
news:Ru*********************@news1.calgary.shaw.ca ...
Dear Gurus,

This is a fairly simple question, but I can't figure out what the answer is. I can easily change my code, but I want to know why I can't do this to
further my knowledge of the C++ language (and OO):

class a
{
public:
a(){ vm(); }
virtual void vm() = 0;
};

class b : public a
{
public:
void vm() { }
};

int main()
{
b B;

return 0;
}

VC++ says: "error LNK2001: unresolved external symbol "public: virtual void __thiscall a::vm(void)"

I understand that 'a' doesn't have a implementation of 'vm', but also I
cannot create an instance of 'a' either (because it has a pure virtual
function) so when I create a 'b' why can't 'a's constructor call 'b's

'vm'?

Whoa dude, you had it there for a minute. Now step back and think about
what you're saying. Why would a base class EVER need to know anything about
any of its subclasses? Inheritance doesn't work that way. When you create
a b, b's constructor gets called, which means a's constructor is going to
get called. But a base class function shouldn't call a subclass function.
Once you're in code for a, all it sees is a.

By the way, just because a is abstract doesn't mean you can't give a
definition for the pure virtual function. It's a common mistake to think
that though. It's often a useful technique to make a function pure virtual,
but then provide a definition that the base classes can call from their
overridden function, to do at least some common work. It might even be all
that some subclasses need to do.
Jul 19 '05 #6

"jeffc" <no****@nowhere.com> wrote in message
news:3f********@news1.prserv.net...
Whoa dude, you had it there for a minute. Now step back and think about
what you're saying. Why would a base class EVER need to know anything about any of its subclasses? Inheritance doesn't work that way. When you create a b, b's constructor gets called, which means a's constructor is going to
get called. But a base class function shouldn't call a subclass function.


I was talking only about the constructor in this case, of course, not the
general case of function overriding. Constructor time is different.
Jul 19 '05 #7
> Whoa dude, you had it there for a minute. Now step back and think about
what you're saying. Why would a base class EVER need to know anything about any of its subclasses? Inheritance doesn't work that way. When you create a b, b's constructor gets called, which means a's constructor is going to
get called. But a base class function shouldn't call a subclass function.
Once you're in code for a, all it sees is a.
I get it now. Whoa dude :) hahaha!
By the way, just because a is abstract doesn't mean you can't give a
definition for the pure virtual function. It's a common mistake to think
that though. It's often a useful technique to make a function pure virtual, but then provide a definition that the base classes can call from their
overridden function, to do at least some common work. It might even be all that some subclasses need to do.


Whoa dude, I did not know that! That could be very useful. Thanks for the
tip!

Quentin.
Jul 19 '05 #8
"Bill Thompson" <bi*****@ixnayontheamspayrgv.rr.com> wrote in message news:<dm*******************@twister.austin.rr.com> ...
"Quentin" <IH*******@SpamSux.com> wrote in message
I'm by no means a guru, and of course you can check the FAQ, but I believe
this is the problem:
Class A is an abstract base class containing an unimplemented virtual
function. Therefore, you cannot call vm() from the Class A constructor,
because in Class A it doesn't exist.

Call vm() from Class B's constructor.

Think about it... why should the compiler allow you to call Class A's vm()
if it has no function body? The compiler is doing you a favor here.

An additional question: were you to derive additional classes from A, how
would the compiler know which instance of vm() to call in A's constructor?


Note that this is only true for calls in constructors. It's perfectly
valid to call an abstract function from any function except from
constructors and destructors (?).

BTW it is the central idea in the Template Method Pattern.

Regards,

Marcelo Pinto
Jul 19 '05 #9
"Marcelo Pinto" <mp****@tecnolink.com.br> wrote in message
news:e3**************************@posting.google.c om...
"Bill Thompson" <bi*****@ixnayontheamspayrgv.rr.com> wrote in message news:<dm*******************@twister.austin.rr.com> ...
"Quentin" <IH*******@SpamSux.com> wrote in message
I'm by no means a guru, and of course you can check the FAQ, but I believe this is the problem:
Class A is an abstract base class containing an unimplemented virtual
function. Therefore, you cannot call vm() from the Class A constructor,
because in Class A it doesn't exist.

Call vm() from Class B's constructor.

Think about it... why should the compiler allow you to call Class A's vm() if it has no function body? The compiler is doing you a favor here.

An additional question: were you to derive additional classes from A, how would the compiler know which instance of vm() to call in A's

constructor?
Note that this is only true for calls in constructors. It's perfectly
valid to call an abstract function from any function except from
constructors and destructors (?).

BTW it is the central idea in the Template Method Pattern.

Regards,

Marcelo Pinto


Yes, of course, after construction the vtable has been initialized. I
should have made it more obvious I was referring to constructors, not
calling virtual functions in general.
Jul 19 '05 #10

"Quentin" <IH*******@SpamSux.com> wrote in message
news:41*********************@news1.calgary.shaw.ca ...
By the way, just because a is abstract doesn't mean you can't give a
definition for the pure virtual function. It's a common mistake to think that though. It's often a useful technique to make a function pure virtual,
but then provide a definition that the base classes can call from their
overridden function, to do at least some common work. It might even be

all
that some subclasses need to do.


Whoa dude, I did not know that! That could be very useful. Thanks for

the tip!


I had a typo - I meant "provide a definition that the *subclasses* can call
from their overridden function".

Example. Program for a football game. You have football players.

class FootballPlayer
class Punter : public FootballPlayer
class DefensiveEnd : public FootballPlayer

You don't have any players on the field that are so generic that you'd
create a FootballPlayer - everyone plays a specific position. Therefore,
you make FootballPlayer abstract. But in case of crazy plays, you want
every player on the field to be able to make a tackle. You might have a
pure virtual function called Tackle() which provides some basic tackling
technique.

class FootballPlayer
{
public:
void Tackle() = 0;
};

You might override Tackle() if there is some special technique defensive
players might use. But there's nothing wrong with defining
void FootballPlayer::Tackle()
{
// tackle in some basic way
}

Then Punter could just do
void Punter::Tackle()
{
FootballPlayer::Tackle(); // the basic base function is good enough
}

The DefensiveEnd might add
void DefensiveEnd::Tackle()
{
FootballPlayer::Tackle();
// plus add a harder hit, or trying to punch the ball away on the way down
}
Jul 19 '05 #11
jeffc <no****@nowhere.com> spoke thus:
You don't have any players on the field that are so generic that you'd
create a FootballPlayer - everyone plays a specific position. Therefore,
you make FootballPlayer abstract. But in case of crazy plays, you want
every player on the field to be able to make a tackle. You might have a
pure virtual function called Tackle() which provides some basic tackling
technique. class FootballPlayer
{
public:
void Tackle() = 0;
}; You might override Tackle() if there is some special technique defensive
players might use. But there's nothing wrong with defining
void FootballPlayer::Tackle()
{
// tackle in some basic way
} Then Punter could just do
void Punter::Tackle()
{
FootballPlayer::Tackle(); // the basic base function is good enough
}


Like football eh? ;) Seriously, I'm still a C++ newb, so I'm not seeing the
point of defining a pure virtual function and then overriding it. Why not
just make it a regular virtual function?

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |

(blank space follows, sorry)











Jul 19 '05 #12

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message news:bk**********@chessie.cirr.com...

Like football eh? ;) Seriously, I'm still a C++ newb, so I'm not seeing the
point of defining a pure virtual function and then overriding it. Why not
just make it a regular virtual function?

Why use function overloading, just give everything seperate names?
Because it makes sense to have the base class behavior impelemented
in a function of the same name, even if you're forced to think about
whether that is the proper behavior (by itself) in a derived class.
Jul 19 '05 #13
Ron Natalie <ro*@sensor.com> spoke thus:
Why use function overloading, just give everything seperate names?
Because it makes sense to have the base class behavior impelemented
in a function of the same name, even if you're forced to think about
whether that is the proper behavior (by itself) in a derived class.


M... (denseness/cluelessness alert!)

I thought the point of a pure virtual function was to force subclasses to
implement it, since the base class explicitly declines to do so. If the base
class wants to provide an implementation of a member function, what is
accomplished by declaring it to be purely virtual? Is it so a class that uses
classes derived from the base can choose to override the base virtual
function......?

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cyberspace.org |
Jul 19 '05 #14

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message news:bk**********@chessie.cirr.com...
Ron Natalie <ro*@sensor.com> spoke thus:
Why use function overloading, just give everything seperate names?
Because it makes sense to have the base class behavior impelemented
in a function of the same name, even if you're forced to think about
whether that is the proper behavior (by itself) in a derived class.
M... (denseness/cluelessness alert!)

I thought the point of a pure virtual function was to force subclasses to
implement it, since the base class explicitly declines to do so.


The first part of your statement is true, the second isn't. It forces the
derived classes (at least those who are going to be concrete) to provide
an implementation, but it doesn't say boo about whether the base class
does or not.
If the base
class wants to provide an implementation of a member function, what is
accomplished by declaring it to be purely virtual?
We just told you, and the football example was provided. I'll give you a more real
world one right out of our main product. Inside we have a bunch of objects that
get passed around generically. They have various functions they implement
(including such common things as the relational operators, serialize output, etc...).
Lets take the serialize function. There is a default behavior of just writing an
encoded version of the object type (which there is obtainable from the base class
via another virtual function). However, that's NOT good enough for many of
the objects. Therefore, I make the base class method pure, so that it MUST
be overridden. This forces the derived class writer to make the decision between
using the default behavior or writing a different implementation. What it doesn't
allow (and we were screwed by this a couple of times before we did this) is
to forget to put an explicit statement of the proper behavior in his class definition.

Is it so a class that uses
classes derived from the base can choose to override the base virtual
function......?


Well a class can always chose to override the function. What it does is force
the derived class to make an explicit statement as to whether he wants the
base behavior or something else.
Jul 19 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: AK | last post by:
Hi all, I have a form which simulates a form collecting a person's info for a job. The form has the field's like fname, lname, address etc. The last field in the form is browse for resume and...
1
by: farzad | last post by:
Hi I try to install php_ming.so in my php . I am using Redhat 8.0 php 4.2.2 apache 2.0.4. I am doing as the howto install file want me to do. as follow....
1
by: Randell D. | last post by:
Folks, I use Apache/PHP with Webazlier to view the log files. I get a number of user agents (web browsers?) that visit the website - For example: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT...
2
by: Alex | last post by:
Is it more time-consuming to troubleshoot or just start from scratch. PHP used to work that's why I'm tempted to just re-install Linux.
0
by: @(none).dk | last post by:
Hi I am not sure whether my new webhotel has setup "AddType jad/jar files" in the apache configuration file. The webhotel has php - so my question is: Can I make something with php that...
3
by: lawrence | last post by:
I do get that MD5() scrambles a password, but how do you then unscrable it? I want to get $password from the user, scrable it, then append it to every link.
8
by: Jeffrey Silverman | last post by:
'nuff said. Just venting... -- Jeffrey D. Silverman | jeffrey AT jhu DOT edu Johns Hopkins University | Baltimore, MD Website | http://www.wse.jhu.edu/newtnotes/
5
by: paul13 | last post by:
This seems weird, but when I use the following code, include 'http://www.foo.com/includes.php'; includedfunction(); I am told that it is a call to an undefined function, but...
2
by: tobias | last post by:
I am new in programming with PHP. I wrote the following code: file name: output.php <?php echo $texto; ?> And I call it on my browser like: http://localhost/cgt/output.php?texto=testing
3
by: lawrence | last post by:
I haven't been able to reach www.php.net for days. Most of the rest of the web is working for me, though I've bad trouble reaching any English sites. Anyone else having trouble?
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.