473,795 Members | 3,081 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Virtual function signature problem

32 New Member
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 3388
Harinezumi
32 New Member
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 Recognized Expert Moderator Expert
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
Harinezumi
32 New Member
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 Recognized Expert Moderator Expert
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::displa y 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::displ ay' : function does not take 1 arguments

The compiler believes you want to call Derived::displa y.

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
Harinezumi
32 New Member
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
17779
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
7315
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
2517
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 pointer or reference to a derived type of the base class's return type. In .NET the overridden virtual function is similar, but an actual parameter of the function can be a derived reference from the base class's reference also. This dichotomy...
20
2021
by: Daniel | last post by:
I have the following three classes class A { public: virtual void f() = 0; }; class B: public A {
7
2565
by: vaividhya | last post by:
We can have virtual destructors.Why we can't have virtual constructors?
13
3664
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
6130
by: asdf | last post by:
They looks so similar. Anybody would like to tell me their differences? Thanks a lot.
6
3313
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
13261
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 already talk about this issue. But I still confused.. This is the simple test code I copied from these messages //////////////////////////////////////////////////////////////////// class Base { virtual void foo(); //*position A* };
0
9519
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10439
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10165
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10001
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9043
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6783
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5437
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5563
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3727
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.