Masking a virtual function?

S

Squeamizh

The subject line probably isn't the best, but I don't know how else to
describe my question.

When I try to compile the code below, my compiler reports an error
(error text is below code sample).

class GrandParent {
virtual void doSomething() = 0;
};

class Parent : public GrandParent {
void doSomething() { std::cout << "blah"; }
};

class Child : public Parent {
bool doSomething() {
Parent::doSomething();
return true;
}
}

Error text is:
error C2555: 'Child::doSomething': overriding virtual function return
type differs and is not covariant from 'Parent::doSomething'


I thought that since Parent's function isn't virtual, I should be able
to define an entirely unrelated function in Child that just happens to
have the same name. Is my compiler being overly picky or am I wrong?

Thanks.
 
B

Bob Hairgrove

The subject line probably isn't the best, but I don't know how else to
describe my question.

When I try to compile the code below, my compiler reports an error
(error text is below code sample).

class GrandParent {
virtual void doSomething() = 0;
};

class Parent : public GrandParent {
void doSomething() { std::cout << "blah"; }
};

class Child : public Parent {
bool doSomething() {
Parent::doSomething();
return true;
}
}

Error text is:
error C2555: 'Child::doSomething': overriding virtual function return
type differs and is not covariant from 'Parent::doSomething'


I thought that since Parent's function isn't virtual, I should be able
to define an entirely unrelated function in Child that just happens to
have the same name. Is my compiler being overly picky or am I wrong?

Unfortunately, you are wrong. Parent's function is virtual if the base
class function is virtual, whether or not Parent::doSomething() is
specified to be virtual. IOW, "virtual" propagates down the class
hierarchy.
 
R

Rolf Magnus

Squeamizh said:
The subject line probably isn't the best, but I don't know how else to
describe my question.

When I try to compile the code below, my compiler reports an error
(error text is below code sample).

class GrandParent {
virtual void doSomething() = 0;
};

class Parent : public GrandParent {
void doSomething() { std::cout << "blah"; }
};

class Child : public Parent {
bool doSomething() {
Parent::doSomething();
return true;
}
}

Error text is:
error C2555: 'Child::doSomething': overriding virtual function return
type differs and is not covariant from 'Parent::doSomething'

That's right.
I thought that since Parent's function isn't virtual,

It is virtual. A function that is virtual in a base class cannot be
"devirtualized" in a derived class.
I should be able to define an entirely unrelated function in Child that
just happens to have the same name.

Yes, if its signature (i.e. parameter list or the c-v qualifiers) differs.
You can't overload functions only by different return type. Btw: This has
nothing to do with the function being virtual.
Is my compiler being overly picky or am I wrong?

You are wrong.
 
B

Ben Radford

Squeamizh said:
The subject line probably isn't the best, but I don't know how else to
describe my question.

When I try to compile the code below, my compiler reports an error
(error text is below code sample).

class GrandParent {
virtual void doSomething() = 0;
};

class Parent : public GrandParent {
void doSomething() { std::cout << "blah"; }
};

class Child : public Parent {
bool doSomething() {
Parent::doSomething();
return true;
}
}

Error text is:
error C2555: 'Child::doSomething': overriding virtual function return
type differs and is not covariant from 'Parent::doSomething'


I thought that since Parent's function isn't virtual, I should be able
to define an entirely unrelated function in Child that just happens to
have the same name. Is my compiler being overly picky or am I wrong?

Thanks.

Imagine a situation like the following:

Child child;
child.doSomething();

Should this invoke child.Child::doSomething() or
child.Parent::doSomething()? AFAIK the C++ standard inhibits the usage
you described to prevent this sort of ambiguity. Since the return type
can be discarded it is not enough to establish a function as being
different from another.

Regards,

Ben
 
L

Luke Meyers

Squeamizh said:
class GrandParent {
virtual void doSomething() = 0;
};

class Parent : public GrandParent {
void doSomething() { std::cout << "blah"; }
};

class Child : public Parent {
bool doSomething() {
Parent::doSomething();
return true;
}
}

Error text is:
error C2555: 'Child::doSomething': overriding virtual function return
type differs and is not covariant from 'Parent::doSomething'

I thought that since Parent's function isn't virtual, I should be able
to define an entirely unrelated function in Child that just happens to
have the same name. Is my compiler being overly picky or am I wrong?

Your compiler's right. I was asking about basically this same issue a
few weeks back. Basically, it turns out that "virtual" cascades
downward through an inheritance hierarchy, so Parent::doSomething *is*
virtual.

Now, a derived class can *hide* a base class's virtual by defining
another function of the same name but a different signature. Note that
the return value is not part of the signature. The only way you can
provide a different return value is if it is a covariant return type --
that is, if it is a pointer or reference to a type T2, where the parent
returns a pointer or reference (respectively) to a type T1, where T2
inherits from T1. In other words, for return-by-reference, you can be
"more specific" about what you're returning, since doing so simply
provides a tighter contract and doesn't break any existing guarantees.

Luke
 
P

Peter_Julian

| The subject line probably isn't the best, but I don't know how else to
| describe my question.
|
| When I try to compile the code below, my compiler reports an error
| (error text is below code sample).
|
| class GrandParent {
| virtual void doSomething() = 0;
| };
|
| class Parent : public GrandParent {
| void doSomething() { std::cout << "blah"; }
| };
|
| class Child : public Parent {
| bool doSomething() {
| Parent::doSomething();
| return true;
| }
| }
|
| Error text is:
| error C2555: 'Child::doSomething': overriding virtual function return
| type differs and is not covariant from 'Parent::doSomething'
|
|
| I thought that since Parent's function isn't virtual, I should be able
| to define an entirely unrelated function in Child that just happens to
| have the same name. Is my compiler being overly picky or am I wrong?

Any member function that is virtual in the base or abstract class is
virtual in the entire inheritence hierarchy.

The return type of a function is not part of its signature. Whether that
function is a non-member, a member function or a virtual member function
is irrelevent.
 

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
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top