473,387 Members | 1,693 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,387 software developers and data experts.

Virtual function signature problem

Hi,
while creating a hierarchy of classes I ran into a strange problem: it seems the compiler doesn't inherit virtual functions with the same name but different signature if only one of them is overridden in a derived class.
This is the smallest piece of code I could see the problem appear:
Expand|Select|Wrap|Line Numbers
  1. class UserType
  2. {
  3. public:
  4.     UserType(float x) : x(x) {}
  5.  
  6.     float x;
  7. };
  8.  
  9. class Base
  10. {
  11. public:
  12.     Base() : data(0) {}
  13.     virtual const UserType& Data() const { return data; }
  14.     virtual void Data(const UserType& value) { data = value; }
  15.  
  16. private:
  17.     UserType data;
  18. };
  19.  
  20. class D1 : public Base
  21. {
  22. };
  23.  
  24. class D2 : public D1
  25. {
  26.     virtual void Data(const UserType& value) { D1::Data(value); }
  27. };
  28.  
  29. int main()
  30. {
  31.     D2 d;
  32.     d.Data();
  33.     return 0;
  34. }
When I try to compile this, I get the following error:

main.cpp: In function `int main()':
main.cpp:32: error: no matching function for call to `D2::T()'
main.cpp:26: error: candidates are: virtual void D2::T(const UserType&)

Why does this happen? I thought that any public function of a base class can be called in a derived, but in this case something is amiss.

Thanks in advance,
Harinezumi
May 23 '08 #1
5 3349
Sorry, I posted the wrong compiler error.
It actually says this:

main.cpp: In function `int main()':
main.cpp:32: error: no matching function for call to `D2::Data()'
main.cpp:26: error: candidates are: virtual void D2::Data(const UserType&)
May 23 '08 #2
weaknessforcats
9,208 Expert Mod 8TB
It says for d2.Data() that there is no Data function that takes 0 arguments.

Your class is:
class D2 : public D1
{
virtual void Data(const UserType& value) { D1::Data(value); }
};
and you can clearly see that Data requires a UserType& argument.


AHA! you say but there is an inherited function from Base that takes 0 arguments:
class Base
{
public:
Base() : data(0) {}
virtual const UserType& Data() const { return data; }
virtual void Data(const UserType& value) { data = value; }

private:
UserType data;
};
What you are seeing here is an example of the C++ principle of dominance.

In a derived class, a member function with the same name as a member function in the base class but with different arguments is said to dominate. Then, when you try to call the base method, the compiler thinks you mean the derived method and your build fails with wrong arguments errors.

You should avoid this situation.

In this case, you have to call the bas class method using the scope resolution operator so the compiler knows exactly which Data function you want:
Expand|Select|Wrap|Line Numbers
  1. int main()
  2. {
  3.     D2 d;
  4.     d.Base::Data();         //OK
  5.     return 0;
  6. }
  7.  
Please note that even if the Base::Data() were private, you would get the same build errors because the access specifiers (public/private/protected) are ingnored when you redefine functions.

BTW: Public data members as in UserType are a big no-no. I would redesign that class so the data members are private. The reason is that you expose your implementaton. That means thst if you redesign UserType all the code that uses the public data member breaks.
May 23 '08 #3
What you are seeing here is an example of the C++ principle of dominance.

In a derived class, a member function with the same name as a member function in the base class but with different arguments is said to dominate. Then, when you try to call the base method, the compiler thinks you mean the derived method and your build fails with wrong arguments errors.
OK, I never heard of this rule before. Can it be turned off somehow? It's usually great that the compiler thinks for itself, but in this case, I'd rather it didn't. I would like to change the behavior of my setter in my derived class, but not the getter. And users of that class shouldn't need to be aware of how these methods are inherited.

Also, after looking up dominance, in all cases it said that it only applies to virtual inheritance. Is that true, or somebody just misunderstood the principle?
May 26 '08 #4
weaknessforcats
9,208 Expert Mod 8TB
Beeswax. Dominance has nothing to do with virtual inheritance. What is does have to do with is you can't overload functions in different scopes. It is the local scope that dominates.

It's the same case with a local variable having the same name as a global variable. When you use the name, you get the local variable. The only way to get the global variable is to use the scope resolution operator. That's what the operator is for: To tell the compiler what scope you are using:

Expand|Select|Wrap|Line Numbers
  1. int val = 10;
  2.  
  3. void func()
  4. {
  5.      int val = 0;
  6.      val += 10;     //increments the local val
  7. }
  8.  
  9. void funcA()
  10. {
  11.      int val = 0;
  12.      ::val += 10;     //increments the global val
  13. }
  14.  



In the example below, the local Derived::display dominates the Base::display.

This code won't compile:
Expand|Select|Wrap|Line Numbers
  1. class Base
  2. {
  3.     public:
  4.           void display(int n);
  5. };
  6. void Base::display(int n)
  7. {
  8.      cout << n << endl;
  9. }
  10. class Derived
  11. {
  12.   public:
  13.       void display();
  14. };
  15. void Derived::display()
  16. {
  17.      cout << 25 << endl;
  18. }
  19. int main()
  20. {
  21.     Derived obj;
  22.     obj.display(10);
  23. }
  24.  
It gets this error:

error C2660: 'Derived::display' : function does not take 1 arguments

The compiler believes you want to call Derived::display.

Use the scope resolution operator to tell the compiler which scope you want:

Expand|Select|Wrap|Line Numbers
  1. int main()
  2. {
  3.     Derived obj;
  4.     obj.Base::display(10);        //OK
  5. }
  6.  
May 26 '08 #5
OK, I understand what dominance does. What I don't get is why doesn't simple member function inheritance happen here, when it would be easier for the compiler than to guess what I wanted to do?
In this case the compiler guesses wrong, because I want to distinguish the member functions through their signatures (which I thought was default).
May 28 '08 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

8
by: Floogle | last post by:
how do i create a virtual == operator. I've tried the following but it's incorrect... class Interface { ... public: virtual bool operator==(const Interface& rhs)const=0;
10
by: Martin Vorbrodt | last post by:
Example code in one of my books intrigues me: class B { public: B* Clone() const { B* p = DoClone(); assert(typeid(*p) == typeid(*this)); return p; }
2
by: Edward Diener | last post by:
In C++ an overridden virtual function in a derived class must have the exact same signature of the function which is overridden in the base class, except for the return type which may return a...
20
by: Daniel | last post by:
I have the following three classes class A { public: virtual void f() = 0; }; class B: public A {
7
by: vaividhya | last post by:
We can have virtual destructors.Why we can't have virtual constructors?
13
by: George | last post by:
Hi all, I'm moving my experince from C to C++ and while so I'm facing some problems with inheritance. Here is my problem: class A { // All share attributes // ....
7
by: asdf | last post by:
They looks so similar. Anybody would like to tell me their differences? Thanks a lot.
6
by: newbie | last post by:
class AbstractBox { public: virtual double area() const = 0; } class BoxA : public AbstractBox { virtual double area() { return 0.1; } } class BoxB : public AbstractBox {
10
by: asm23 | last post by:
Hi, I'm using Intel C++ compiler 9 to compiler a project. But, there are a lot of warning saying like "virtual function override intended....". I searched old messages in Google groups, someone...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.