Inherited Class - Member Functions of Same Name

Feb 12, 2019 at 12:38pm
If two classes have methods with the exact same name, and one class inherits the other, how does the program know which method should be called? Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class One
{
public:
	int x, y;
	
	void Print()
	{
		std::cout << "x = " << x << std::endl;
		std::cout << "y = " << y << std::endl;
	}
};

class Two : public One
{
public:
	int X, Y;

	void Print()
	{
		std::cout << "X = " << X << std::endl;
		std::cout << "Y = " << Y << std::endl;
	}
};

int main()
{
	Two two;
	
	two.x = 10;
	two.y = 15;
	two.X = 20;
	two.Y = 30;
	two.Print();

	std::cin.get();
}


Output:

"X = 20"
"Y = 30"

So why did the program decide to call the 'Two' member function 'Print()' rather than the inherited 'One' member function 'Print()', and how is this decision made?

Last edited on Feb 12, 2019 at 12:45pm
Feb 12, 2019 at 12:55pm
I'm pretty sure someone will answer your question in a competent way, so I won't try. But I think this issue is merely a problem of bad design on your part.

First it's a bad idea to have variables in your public part of your classes. It's a good habit to have accessor and mutator functions to change their values.

Second you should name your variables accordingly to what they hold a value for and not just x, y, z, i, j etc.

Therefore their accessors and mutators would have a name to go along with that.

What's the point of having an inherited class that is identical to the mother class? You'd better just create a second object of the first class.

I changed your code a bit to illustrate my purpose
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>

class One
{
    private:
        int one_x, one_y;

    public:
	
	    void change_one_x(int new_x) { one_x = new_x; }
	    void change_one_y(int new_y) { one_y = new_y; }
	
	    void PrintOneVars()
	    {
	    	std::cout << "one_x = " << one_x << std::endl;
	    	std::cout << "one_y = " << one_y << std::endl;
	    }
};

class Two : public One
{
    private:
        int two_x, two_y;

    public:
	
	    void change_two_x(int new_x) { two_x = new_x; }
	    void change_two_y(int new_y) { two_y = new_y; }
	
	    void PrintTwoVars()
	    {
	    	std::cout << "two_x = " << two_x << std::endl;
	    	std::cout << "two_y = " << two_y << std::endl;
	    }
};



int main()
{
	Two two;
	
	two.change_two_x(10);
	two.change_two_y(15);
	two.change_one_x(20);
	two.change_one_y(30);

	two.PrintOneVars();
	two.PrintTwoVars();

	std::cin.get();
}


Output:
one_x = 20
one_y = 30
two_x = 10
two_y = 15

Exit code: 0 (normal program termination)
Last edited on Feb 12, 2019 at 12:59pm
Feb 12, 2019 at 1:00pm
H00G0: This isn't a program that I am actually planning to use... I just created this quickly as an example. There is no point in having an inherited class that is identical to the base class, I just wanted to try and understand how the program would distinguish between the two functions in this kind of situation.
Feb 12, 2019 at 1:04pm
Right my bad for not guessing that then.

I can't really answer you accurately, as I said. My best guess would be that if you have an overloaded function between the mother and child class, the first one that is encountered will be the one called i.e the one from the inherited class.

I'd be interested as well, if someone could explain in detail how this works..
Feb 12, 2019 at 1:40pm
It's call "shadowing" a function. You declared a variable of type Two, so it will choose Two's (or whatever the "closest" subclass is in the case of more levels of inheritance) member function. In renders One's member function inaccessible unless you cast the object and slice it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

class One
{
  public:
	int x, y;
	
	void Print()
	{
		std::cout << "x = " << x << std::endl;
		std::cout << "y = " << y << std::endl;
	}
};

class Two : public One
{
  public:
	int X, Y;

	void Print()
	{
		std::cout << "X = " << X << std::endl;
		std::cout << "Y = " << Y << std::endl;
	}
};

int main()
{
	Two two;
	
	two.x = 10;
	two.y = 15;
	two.X = 20;
	two.Y = 30;
	two.Print();
	
	One one = two; // slice two into one
    one.Print();
}

As Hoogo said, it's probably bad design to have to do this. I would avoid anything where the subclass and superclass have public variables that differ by just capitalization. If polymorphism is wanted, then virtual functions should be used.
Last edited on Feb 12, 2019 at 11:31pm
Feb 12, 2019 at 1:47pm
Ganado:

Thanks. I'm reading up on virtual functions now.
Feb 12, 2019 at 2:53pm
You can also get to the base class functionality by calling it explicitly. I believe the syntax is:

two.One::Print()
Feb 12, 2019 at 2:58pm
Good advice, I had forgotten about that in my post. So it isn't completely inaccessible, then.
Topic archived. No new replies allowed.