another c++ inheretence/virtual quesion

L

laniik

Hi. I have a simple question, but I couldnt find the answer in any
literature online.

i have a base class A, that has some functions. now, my understanding
of virtual functions means that in:

class A {
virtual void foo() = 0;
void bar() {cout<<"bar"<<endl;}
};

class B : public A {
void foo() {cout<<"foo"<<endl;}
void bar() {cout<<"bar2"<<endl;}
};

every class B that derives class A *must* define foo or I get a linker
error.

also, if class B defines bar, it will call the bar from class A rather
than B. i.e. print out bar rather than bar2

What i want is to have a function defined in A that if it isnt defined
in B, then it uses the one in A

if it is defined in B, then it uses the one in B. (but it doesnt
*have* to be defined) how do i do this? thanks!

oliver
 
R

Reddsci2001

This is pretty much done in your example. Since you have bar() defined in
A, if it is not defined in B the version in the base class will be called
(provided all pure virtual functions are defined which you have done)
 
L

laniik

thats what I first thought, but when i compiled and tested it out,
calling

B b;
b.bar();

would print out "bar" rather than "bar2"
 
D

David White

laniik said:
Hi. I have a simple question, but I couldnt find the answer in any
literature online.

i have a base class A, that has some functions. now, my understanding
of virtual functions means that in:

class A {
virtual void foo() = 0;
void bar() {cout<<"bar"<<endl;}
};

class B : public A {
void foo() {cout<<"foo"<<endl;}
void bar() {cout<<"bar2"<<endl;}
};

every class B that derives class A *must* define foo or I get a linker
error.

No. You get a compiler error if you try to create an instance of A, or a
class derived directly or indirectly from A that does not provide or inherit
a non-pure override of A::foo.

You get a linker error if you call a function that you've declared but
haven't defined anywhere, whether it's virtual or not. You might or might
not get a linker error for declaring a non-pure virtual function that you
haven't defined, even if you don't call it. That probably depends on the
linker, but certainly the ones I've used would give an error.
also, if class B defines bar, it will call the bar from class A rather
than B. i.e. print out bar rather than bar2

What do you mean by 'it' in this statement? B::bar hides A::bar (and B::foo
hides A::foo for that matter). If you have a B, B& or B* and you call bar(),
then B::bar will be called.
What i want is to have a function defined in A that if it isnt defined
in B, then it uses the one in A

if it is defined in B, then it uses the one in B. (but it doesnt
*have* to be defined) how do i do this? thanks!

That just happens naturally. That's why it's called *inheritance*. If a
given class doesn't have a particular member, then it will inherit it from
the nearest base class that has it. Try removing bar() from B, then create a
B object and call its bar(). A::bar will be called.

DW
 
S

Stephen Howe

also, if class B defines bar, it will call the bar from class A rather
than B. i.e. print out bar rather than bar2

No it won't.

A *pa = new B;
B *pb = new B;

pa->foo(); // will display "foo"
pa->bar(); // will display "bar"

pb->foo(); // will display "foo"
pb->bar(); // will display "bar2"
What i want is to have a function defined in A that if it isnt defined
in B, then it uses the one in A

if it is defined in B, then it uses the one in B. (but it doesnt
*have* to be defined) how do i do this? thanks!

It depends on what object type "it" is.
virtual member functions are dynamically bound.
non-virtual member functions depend on the type of the object.

Stephen Howe
 
R

Reddsci2001

I put basically your same code in from your top level message and it
worked fine:
#include <iostream>

using std::cout;

class A
{
public:
A(){}
virtual void foo()=0;
void bar()
{
cout<<"bar\n";
}
};

class B : public A
{
public:
B(){}
virtual void foo()
{
cout<<"Foo\n";
}
void bar()
{
cout<<"bar2\n";
}
};

int main(int argc, char **argv)
{
B b;
b.bar();

return 0;
}

results in "bar2" being printed.
 
S

Stephen Howe

thats what I first thought, but when i compiled and tested it out,
calling

B b;
b.bar();

would print out "bar" rather than "bar2"

Something wrong then.
You should see "bar2".

Stephen Howe
 
L

laniik

i dont know what to say, im looking at it right now, its definitly
calling the function from the base class.

this is the code posted above.

i am using g++ on a solaris machine. any ideas?
 
D

David White

laniik said:
found the bug: turns out you need to have bar declared virtual as
well...

No you don't. The behaviour you have described is wrong, and it is hard to
believe that any reasonably tried and tested compiler could have such a
fundamental problem. I suggest that you post the complete and exact code
you've compiled and run by pasting it from the file you compiled into your
newsreader (the code you originally posted is not a complete program, nor
does it compile as is).

DW
 
L

laniik

class A {
public:
void go() {cout<<"1"<<endl;}
};

class B : public A{
public:
void go() {cout<<"2"<<endl;}
};

int main()
{
B b;
b.go();
return 0;
}

tried this in visual studio .net 2003, printed "2"
tried this on solaris (not sure what version) with g++ (also not sure
what version) printed "1"
 
D

David White

laniik said:
class A {
public:
void go() {cout<<"1"<<endl;}
};

class B : public A{
public:
void go() {cout<<"2"<<endl;}
};

int main()
{
B b;
b.go();
return 0;
}

This still isn't complete and can't be what you compiled. You didn't
#include <iostream> and you haven't got any std::. It probably doesn't
matter, assuming that all that's missing from your post is the bare minimum
to get it to compile, but when a program behaves as wrongly as you describe,
it's best to post _exactly_ what you compiled to remove all doubt that
something you haven't included in your post is causing the problem.
tried this in visual studio .net 2003, printed "2"

As it should.
tried this on solaris (not sure what version) with g++ (also not sure
what version) printed "1"

Well, that's amazing.

DW
 
L

laniik

yea i cant cut and paste because i am using a differnt computer for the
newsgroups as the coding. but regardless, all that was missing was the
#include and the namespace.

so, it does perform as desired when i make the functions virtual, is
there any reason i wouldnt want to just do that?

thanks
 
L

Larry I Smith

laniik said:
class A {
public:
void go() {cout<<"1"<<endl;}
};

class B : public A{
public:
void go() {cout<<"2"<<endl;}
};

int main()
{
B b;
b.go();
return 0;
}

tried this in visual studio .net 2003, printed "2"
tried this on solaris (not sure what version) with g++ (also not sure
what version) printed "1"

This prints "2" when compiled with GCC g++ v3.3.4 on
linux (SuSE Pro v9.2):

#include <iostream>

class A {
public:
void go() {std::cout << "1" << std::endl;}
};

class B : public A{
public:
void go() {std::cout << "2" << std::endl;}
};

int main()
{
B b;
b.go();
return 0;
}

Regards,
Larry
 
D

David White

laniik said:
yea i cant cut and paste because i am using a differnt computer for the
newsgroups as the coding. but regardless, all that was missing was the
#include and the namespace.

so, it does perform as desired when i make the functions virtual, is
there any reason i wouldnt want to just do that?

It is very unusual for a function such as your 'go' not to be virtual. If
your object is really a B then almost always you would want to call B::go
even if you access it through an A& or A*, e.g.,
B b;
b.go(); // 1
A &a = b;
a.go(); // 2

Only if you actually wanted B::go to be called in case 1 and A::go to be
called in case 2 would you not make it virtual. The reason is that it's the
same object in each case, so you normally want the same function to be
called. This is object-oriented polymorphism. So, unless you have a
compelling reason not to, you should make it virtual (and you'll need a
virtual destructor in A if you do).

DW
 
K

Karl Heinz Buchegger

laniik said:
yea i cant cut and paste because i am using a differnt computer for the
newsgroups as the coding. but regardless, all that was missing was the
#include and the namespace.

so, it does perform as desired when i make the functions virtual, is
there any reason i wouldnt want to just do that?

If that code really perfomrs that way on solaris, then there
is only one thing you want to do: get a different compiler, it
has a strange and serious bug. There is no point in using
it any longer.

But honestly: I doubt that this compiler has that bug. A bug like
this would be discovered in even the simplest compiler tests.
 
L

laniik

well, i went and got a new g++, and it works fine now. soooo dunno why
it wasnt working. before

but thanks david, that helps me understand the virtual/nonvirtual
distinction more.

oliver
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top