I created a class that has virtual overloaded functions in the base class. I want to overwrite the virtual overloaded function in the base class in a derived class. The code is as follows:
#include <iostream.h>
Class B {
Private
int nnumber;
Public
virtual void Test () {
cout << "b::test () \ n";
virtual void Test (int x) {
Nnumber = x; Assign an incoming parameter to a private member
cout << "b::test (int x) \ n";
}
};
Class D:public B {
Public
Test (void) hide b::test (int)
virtual void Test () {
cout << "d::test () \ n";
}
};
void Main (int argc, char* argv[])
{
D D; Instances of derived classes
D.test (); Ok
D.test (a); Line of code generating compilation errors
}
There are two overloaded test functions in the base class. When I overwrite one of these functions in a derived class, I think the other one should inherit in the derived class, but the error message appears at compile time:
... C2660: ' Test ': function does not take 1 parameters
Can I overload and overwrite a function at the same time without giving up the polymorphic behavior?
Many C + + programmers are puzzled by this problem, and in order to solve this puzzle, there are two concepts you must be clear about. One is the overload, the other is the name space. From an overloaded perspective, you might think that C + + should work the way you think, that is, if a derived class modifies only one of the overloaded functions, the other should be inherited in the usual way. But from the point of view of namespaces, when C + + tries to resolve a symbol name, it searches from near to far, first looking for the local variable, then the class member name, then the base class name, the global variable .... Once the compiler resolves the name, it terminates the parsing process. If you encounter the same symbol name in a different namespace range, then it has no idea. In your code, once the compiler determines that the name "Test" appears in Class D, its name space is Class D. Whether you call test without parameters, or call Test (17) with an integer parameter, the compiler follows the rule to solve the name problem. For the test (int x) function with an integer parameter, once the compiler determines that the function name test lives in Class D, it terminates the scope probe and then looks for the function that matches the parameter. Because it does not find a function with an integer parameter in Class D, an error is given. At this point the compiler considers the function d::test (void) to hide the function b::test (int). You might ask, why do you do it this way? Good question. To find out, refer to Bjarne Stroustrup's C + + annotation reference manual (section 13.1). Simply put, searching for overloaded functions that match a signature deep in the class hierarchy is more likely to cause confusion than not searching.
So how do you solve the problems that arise? It's easy. Simply create another test function in the derived class that explicitly calls the base class, such as:
class D : public B {
public:
virtual void test(int x) { B::test(x); }
……
};
So, D has two test functions, and the problem is solved. There is another solution to this problem: using the "using" keyword in a derived class. Such as:
class D : public B {
public:
using B::test;
// 改写test
virtual void test() {
cout << "D::test()\n";
}
};
This keyword brings the b::test into Class D. The advantage of this is that when Class B expands more test-overloaded functions, you don't have to rewrite the code for Class D. This saves a lot of things. As long as you use the Using keyword, it means that all overloaded B::test functions Enter Class D and are inherited. This trait may be a good thing for some people, but a disadvantage for others, depending on what you are going to do. If you want to hide some test functions from users of Class D, you can use the first method (explicitly call the base class), or make the function you want to hide into a private or protected type. If you've read Scott's book effective C + +, you can also use the Using keyword to subtly guarantee the privacy of the base class.class B {
public:
func1();
func2(double d);
virtual test();
virtual test(int x);
};
// D 从B中秘密派生
class D : private B {
public:
// 让所有 B::test 函数为 public类型
using B::test;
};
Obviously, this method is useful when you want to completely hide class B, but if you want to expose individual functions in B, this method is not so good.