I created a class with a base class containing a virtual overload function. I want to rewrite the virtual overload function in the base class in the derived class. The Code is as follows:
01.
#include < iostream.h >
02.
03.
class
B {
04.
private
:
05.
int
nNumber;
06.
public
:
07.
virtual
void
test() {
08.
cout <<
"B::test()\n"
;
}
09.
virtual
void
test(
int
x) {
10.
nNumber = x;
// Assign the input parameter to a private member
11.
cout <<
"B::test(int x)\n"
;
12.
}
13.
};
14.
15.
class
D :
public
B {
16.
public
:
17.
// Test (void) Hide B: Test (INT)
18.
virtual
void
test() {
19.
cout <<
"D::test()\n"
;
20.
}
21.
};
22.
23.
void
main(
int
argc,
char
* argv[])
24.
{
25.
D d;
// Instance of the derived class
26.
d.test();
// OK
27.
d.test(17);
// Generate a compilation error code line
28.
}
The base class contains two overloaded test functions. When I rewrite a function in a derived class, I think another function should be inherited from the derived class, but the following error message appears during compilation:
... C2660: ''test'': function does not take 1 Parameters
Can I reload and rewrite a function at the same time without giving up polymorphism?
Many C ++ programmers are confused about this problem. To solve this problem, you must understand two concepts. One is overload and the other is namespace. From the perspective of overloading, you may think that C ++ should work in the way you think; that is, if the derived class only modifies the behavior of one of the overloaded functions, the other one should be inherited in the usual way. But from the perspective of namespace, when C ++ tries to solve a symbolic name, it searches from near to far. It first finds the local variable and then the class member name, next is the base class name, global variable ....... Once the compiler resolves the name, it terminates the parsing process. If you encounter the same symbol name in different namespace ranges, it has no idea. In your code, once the compiler determines that the name "test" appears in Class D, its namespace is Class D. Whether you call test without parameters or test (17) with an integer parameter, the compiler follows this rule to solve the name problem. For test (INT) with Integer Parameters
X) function. Once the compiler determines that the function name test is in Class D, it terminates the range probing and searches for the function that matches the parameter. Because it does not find a function with an integer parameter in Class D, an error is returned. The compiler assumes that function D: Test (void) hides function B: Test (INT ). You may ask, why is this approach necessary? Good question. For more information, see section 13.1 ). Simply put, searching for overloaded functions that match a signature in the depth of the class hierarchy is more likely to cause confusion than not searching.
So how can we solve the above problems? Easy. You only need to create another explicit call to the test function of the base class in the derived class, such:
1.
class
D :
public
B {
2.
public
:
3.
virtual
void
test(
int
x) { B::test(x); }
4.
……
5.
};
In this way, D has two test functions, and the problem is also solved. In fact, there is another solution to this problem: use the "using" keyword in the derived class. For example:
1.
class
D :
public
B {
2.
public
:
3.
using
B::test;
4.
// Rewrite Test
5.
virtual
void
test() {
6.
cout <<
"D::test()\n"
;
7.
}
8.
};
This keyword brings B: Test into Class D. It has the advantage that when class B extends more test overload functions, you do not have to rewrite the code of class D. This saves a lot of trouble. As long as you use the Using Keyword, it means that all the overloaded B: test functions Enter Class D and are inherited. This feature may be an advantage for some people, but it is a disadvantage for others, depending on what you want to do. If you want to hide some test functions to users of class D, you can use the first method (explicitly calling the base class) or make the function you want to hide private or protected. If you have read Scott's book Objective C ++, you can also use the using keyword in the second way to cleverly ensure the private hiding of the base class.
01.
class
B {
02.
public
:
03.
func1();
04.
func2(
double
d);
05.
virtual
test();
06.
virtual
test(
int
x);
07.
};
08.
09.
// D secret derived from B
10.
class
D :
private
B {
11.
public
:
12.
// Set all function B: Test to public.
13.
using
B::test;
14.
};
Obviously, this method is useful when you want to completely hide Class B, but if you want to expose individual functions in Class B, this method is not that good.
References: <a hreaf = http://blog.csdn.net/anjy/article/details/1715297/>