Click here to Skip to main content
15,891,682 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I'm stuck in a practice project on inheritance and polymorphism, where we were asked to expand the base struct host by coding its derived struct xhost.

We were not allowed to modify host.h:
C++
#ifndef HOST_H
#define HOST_H

#include <string>
#include <iostream>

struct host {
/////////snap//////////
private:
    virtual void handle_recv(const host&, const std::string&) const {};
};

#endif


And my xhost looks like this in (part of) 1.cpp:

C++
#include "host.h"
using namespace std;

struct xhost : public host
{
    virtual void send(const host &other, const string &s) const
    {
        string message = s;

        for (int i = 0; i != splugList.size(); i++)
        {
            message = (*(splugList[i]))(message);
        }

        cout << "[" << name << " -> " << other.name << "] " << message << std::endl;

        other.handle_recv(*this, s);//////////////////////ERROR HERE
    }

/////////snap//////////

private:
    virtual void handle_recv(const host &other, const string &s) const
    {
        string message = s;

        for (int i = 0; i != rplugList.size(); i++)
        {
            (*(rplugList[i]))(other, *this, message);
        }
    }
};


The compiler said I was trying to access private member function handle_recv in base class host, which is of course an error. However, I don't understand why it was base class function being accessed; I thought that since handle_recv is a virtual function and other is a reference, it would dynamically bind to handle_recv defined in xhost but not the one in host?
Posted
Comments
Philippe Mori 14-May-15 12:50pm    
It has to be protected so that derived class can access it.
Member 11212276 14-May-15 13:07pm    
Do you mean I have to modify the base class in host.h? But it's not allowed. Is there a way to call handle_recv defined in xhost without modifying host?
Philippe Mori 14-May-15 13:13pm    
You cannot. Either you are not supposed to call the method and it was made private for that reason or it was made private by error and you need to fix it.
Member 11212276 14-May-15 13:22pm    
I think there might be some misunderstanding... I never intended to access handle_recv in host class. What I wanted to do is to access handle_recv in xhost. I thought that being a virtual function this can be done by dynamic binding. But obviously my attempt was incorrect but I don't know where I made my mistake.

To be more specific I think I did exactly the same thing as done here:
http://stackoverflow.com/questions/3610936/why-can-i-access-a-derived-private-member-function-via-a-base-class-pointer-to-a
But it seems that it worked for him but not me. Weird...
Philippe Mori 14-May-15 13:58pm    
The example on Stack Overflow has a public member in the base class. It is a totally different case.

In you case, you are calling other.handle_recv. Since other is a host (and not an xhost), you need public access to call it.

A private member can only be accessed from the class itself and not derived classes. It can access field in itself or other object of the same type.

As I have already mentionned, either, you are not using the xhost class as intended and don't need public access to handle_recv or the class was not properly designed (wrong access specifier).

Each languages has its own rules for accessibility. You simply have to conform to those rule. In C#, for example, it is illegal to declare a virtual function to be private. In either case, public access is required to access a function defined in another class.

Protected member allows derived class to access the field but only on this. Acces to other objects require public access.


1 solution

Okay I think I figure it out now... It was my bad for not fully understanding the specifications of the practice project (and not noticing it). The specs were very long, so I didn't include all of them in my question, which also led to further confusions.

For whatever it's worth I'll try to document the cause of this mess:

What send function defined in xhost was expected to do was:
1. After doing stuff above the ///ERROR line, check whether the argument reference other is bound to a host or an xhost.
2. If other is bound to an xhost : call other(i.e. an xhost)'s member function handle_recv.
And if other is bound to a host : DO NOTHING. (f%^&*%$$##@##$ me....)

So what Philippe Mori said was correct, but not really related to the mess here (which is 100% my bad. Sorry...). The "solution" could simply be replacing the ///ERROR line by something like:

C++
if (typeid(other) == typeid(const xhost &))
dynamic_cast<const xhost="">(other).handle_recv(*this, message);
 
Share this answer
 
v3
Comments
Andreas Gieriet 15-May-15 5:39am    
This is a severly broken design if you have to apply such hacks.
Andi
Philippe Mori 15-May-15 7:39am    
Effectively, this is still very suspicious... But as it seems to be a practice project, maybe they want to know what the newcomer would do in such case.
Andreas Gieriet 15-May-15 7:58am    
Polymorphism and access qualifiers are orthogonal, i.e. independent.
Calling a private method on any object of static type other than the own type is rejected by the compiler, independent of the dynamic type.
private virtual only makes sense if in the base class (which declares such a method as first one in the inheritance tree) some other method calls that method on some polymorphic object. E.g. the send method sould be implemented in the base class (and call there the host_recv).
Cheers
Andi

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900