Cannot access protected from base class?

N

Nephi Immortal

I discussed functionoids and pointer to member functions a long time
ago. The template is the best option over functionoids because of the
performance issue. Unfortunately, template does not support pointer
to member function array.
I am surprised to see that C++ Compiler reports an error to say any
member function cannot access to protected from base class, but
ordinary function worked. Very absurb?


class Obj1
{
protected:
static void Run1()
{
}

void errRun1()
{
}
};

class Obj2
{
protected:
static void Run2()
{
}

void errRun2()
{
}
};

class Obj3
{
protected:
static void Run3()
{
}

void errRun3()
{
}
};

class Obj :
public Obj1,
public Obj2,
public Obj3
{
public:
void Run( int index )
{
static void ( * const pRun[ 3 ] )() =
{
Run1,
Run2,
Run3
};

pRun[ index ]();
}

void errRun( int index )
{
static void ( Obj::* const pRun[ 3 ] )() =
{
&Obj1::errRun1,
&Obj2::errRun2,
&Obj3::errRun3
};

( this->*pRun[ index ] )();
}
};


int main()
{
Obj obj;

obj.Run( 0 );
obj.Run( 1 );
obj.Run( 2 );

obj.errRun( 0 );
obj.errRun( 1 );
obj.errRun( 2 );

return 0;
}

Debug Win32 ------
Main.cpp
c:\my projects\main.cpp(315): error C2248: 'Obj1::errRun1' : cannot
access protected member declared in class 'Obj1'
c:\my projects\main.cpp(264) : see declaration of
'Obj1::errRun1'
c:\my projects\main.cpp(258) : see declaration of 'Obj1'
c:\my projects\main.cpp(316): error C2248: 'Obj2::errRun2' : cannot
access protected member declared in class 'Obj2'
c:\my projects\main.cpp(276) : see declaration of
'Obj2::errRun2'
c:\my projects\main.cpp(270) : see declaration of 'Obj2'
c:\my projects\main.cpp(318): error C2248: 'Obj3::errRun3' : cannot
access protected member declared in class 'Obj3'
c:\my projects\main.cpp(288) : see declaration of
'Obj3::errRun3'
c:\my projects\main.cpp(282) : see declaration of 'Obj3'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
==========

Can you please answer my question? Can hundred of base classes or
thousands of base classes be inherited into ONE derived class through
multiple inheritance? The option is the best if derived class has the
ability to create large pointer to member function array in order to
create command object.
 
R

Richard Damon

I discussed functionoids and pointer to member functions a long time
ago. The template is the best option over functionoids because of the
performance issue. Unfortunately, template does not support pointer
to member function array.
I am surprised to see that C++ Compiler reports an error to say any
member function cannot access to protected from base class, but
ordinary function worked. Very absurb?

A derived class can only access the protected parts of a base camp
through the derived class, not directly from the base camp.

In your example, rather than using Obj1::run, use Obj::run. since Obj
has inherited them, it can access them there.

I will also add that this structure seems awkward. While having a large
number of base classes is allowed, it feels like inheritance is being
forced in a place where it really doesn't fit.
 
N

Nephi Immortal

A derived class can only access the protected parts of a base camp
through the derived class, not directly from the base camp.

In your example, rather than using Obj1::run, use Obj::run. since Obj
has inherited them, it can access them there.

I will also add that this structure seems awkward. While having a large
number of base classes is allowed, it feels like inheritance is being
forced in a place where it really doesn't fit.

I understand, but I wonder if large number of base classes violate
rule and needs to make sure if more memory is sufficient.
 
R

Richard Damon

I understand, but I wonder if large number of base classes violate
rule and needs to make sure if more memory is sufficient.

A large number of base classes do not violate an inherent rule in C++.
You will likely end up with a large object, as it needs to store all the
base class members within it. It is possible that this may cause you to
run out of memory, it somewhat depends on how many copies of this object
are created.

I do think it is a sign of a problematical design.
 
N

Nephi Immortal

A large number of base classes do not violate an inherent rule in C++.
You will likely end up with a large object, as it needs to store all the
base class members within it. It is possible that this may cause you to
run out of memory, it somewhat depends on how many copies of this object
are created.

I do think it is a sign of a problematical design.- Hide quoted text -

- Show quoted text -

I am aware of design flaw, but careful design is better. Large
number of base classes into one derived class is the option to replace
virtual functions because of the performance issue and template is not
the option unless you want pointer to member function array.
All member functions in each base class should be static. The
derived class will allocate approximately 4K to 32K memory if memory
contains derived class’ pointer and array of indirect pointers.
You can always create many copies of derived objects, but static
member functions are shared by derived objects. You create interface
class. It includes one derived object definition in the class body.
The client can select the number of objects before interface does the
job to process the derived object such as command object.

For example:

class Interface
{
public:
void Run( int index )
{
cmdList.Execute( index );
}

private:
derivedObject cmdList;
};


If you think that it is design flaw, please demonstrate another
option.
 
I

Ian Collins

I am aware of design flaw, but careful design is better. Large
number of base classes into one derived class is the option to replace
virtual functions because of the performance issue and template is not
the option unless you want pointer to member function array.

What sort of a performance issue have you measured?

What makes templates unsuitable? I don't understand the context of
"unless you want pointer to member function array".
If you think that it is design flaw, please demonstrate another
option.

Exactly what problem are you trying to solve?
 
R

Richard Damon

I am aware of design flaw, but careful design is better. Large
number of base classes into one derived class is the option to replace
virtual functions because of the performance issue and template is not
the option unless you want pointer to member function array.
All member functions in each base class should be static. The
derived class will allocate approximately 4K to 32K memory if memory
contains derived class’ pointer and array of indirect pointers.
You can always create many copies of derived objects, but static
member functions are shared by derived objects. You create interface
class. It includes one derived object definition in the class body.
The client can select the number of objects before interface does the
job to process the derived object such as command object.

For example:

class Interface
{
public:
void Run( int index )
{
cmdList.Execute( index );
}

private:
derivedObject cmdList;
};


If you think that it is design flaw, please demonstrate another
option.

I am not sure where you think you are going to gain in performance. Your
dispatch function is apt to be as slow if not slower than a virtual
function call, and your arrays of function pointers about as big
combined as the virtual tables. If the base classes don't contain state,
than composing them into this one super object doesn't by you anything,
and if they do, your derived class is going to be very large since it
has all of them.
 
N

Nephi Immortal

I am not sure where you think you are going to gain in performance. Your
dispatch function is apt to be as slow if not slower than a virtual
function call, and your arrays of function pointers about as big
combined as the virtual tables. If the base classes don't contain state,
than composing them into this one super object doesn't by you anything,
and if they do, your derived class is going to be very large since it
has all of them.- Hide quoted text -

- Show quoted text -

If you look at pointer to member function in C++ FAQ Lite, you will
understand that it talks about functionoids. It does say that if
performance is an issue, go ahead and use template instead of virtual
function.
I clarify to say why I can’t use template because template does not
support pointer to member function array, but only one pointer to
member function is supported.

For example:

template< typename Obj, typename Fn >
void Run( Obj *pObj, Fn pFn )
{
( pObj->*pFn )();
}

If you use this function above, where is pointer to member function
array? If it exists, you can only select one member function and put
it into Run’s parameter list.
You saw my previous code above. It has static pointer to member
function array in derived class’ Run( int index ).
 
R

Richard Damon

If you look at pointer to member function in C++ FAQ Lite, you will
understand that it talks about functionoids. It does say that if
performance is an issue, go ahead and use template instead of virtual
function.
I clarify to say why I can’t use template because template does not
support pointer to member function array, but only one pointer to
member function is supported.

For example:

template< typename Obj, typename Fn>
void Run( Obj *pObj, Fn pFn )
{
( pObj->*pFn )();
}

If you use this function above, where is pointer to member function
array? If it exists, you can only select one member function and put
it into Run’s parameter list.
You saw my previous code above. It has static pointer to member
function array in derived class’ Run( int index ).


The issue is that the gain you might get for using the template, you
have lost by having to do the array lookup. I will also point out that
you don't need the template at all in your design, all your functions
can have the same type (pointer to member function of type derived), and
all can take the same type of object, derived.

I think you are also being confused on what the FAQ says, the
improvement that the functionoid can gain over the function call is when
the compiler can see at compile time the type info and thus expand the
template inline, and thus remove the function call. If you know which
function to call, calling it directly will of course be slightly faster
than going through the dispatch table, but your program structure is
explicitly denying this operation by making them protected. Unless there
is something more to be done in the dispatch routine, there is no reason
they need to be protected.

I think that you need to step back from the design and rather than
figure out which toys sound interesting to use, ask yourself what REALLY
needs to be done (not HOW, but WHAT), and then look at the simplest way
to achieve that.

From what I have seen so far, all the objects being created so far are
extraneous since they are holding no information, only disjoint pieces
of code. If they do need to store state, does one client really need ALL
of them present?

You also talk about gaining performance, have you actually implemented
the straight forward method and found that the calling overhead is a
significant factor? The way you talk about the runctions "running
commands" makes it sound like they do real work, which probably
overshadows and slight inefficiencies in the calling.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top