471,594 Members | 2,028 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,594 software developers and data experts.

Get parent class function pointer

Hi,

the following sample code shows a compiler error I get trying to build
some old code with the last CL compiler (vers 13.10.3077):

//----- begin
#include <iostream>

namespace ns
{
class base
{
public:
base() {}
virtual ~base() {}
protected:
void Call() { std::cout << "OK" << std::endl; }
};

class derived : public base
{
public:
void Start()
{
typedef void (ns::base::* typeCall)(void);
typeCall fnCall;
fnCall = &ns::base::Call; // this is the line # 21
(this->*fnCall)();
}
};
}
int main()
{
ns::derived d;
d.Start();

return 0;
}
//----- end

I get the following compiler message error at line 21:

main.cpp(21): error C2248: 'ns::base::Call' : cannot access protected
member declared in class 'ns::base'

Workaround: if I remove the ampersand all works fine.

I like to know if the line # 21 is really illegal.

thanks.
Marco.
Nov 16 '05 #1
6 2476
I wouldn't like to trawl through the standard on this one, but I suspect
that the error is correct.

A derived class method is only allowed to access protected members in base
when base is acting as derived's base class. Thus:

class derived : public base
{
public:
void Start()
{
derived objA;
objA.Call (); // Compiles OK

base objB; // Or a different derived class
objB.Call (); // Compiler error
}
};

So to make your code compile, replace:

fnCall = &ns::base::Call;

with

fnCall = &ns::derived::Call;

which works even though Call () is not overridden in derived.

If you do have a derived implementation of Call, and you still want
base::Call, then

fnCall = &ns::derived::base::Call;

will do the trick, but only if Call () is non-virtual. If it is virtual, you
get derived::Call.

Hope this helps,

Jasper Kent.
"marco_segurini" <ma***********@virgilio.it> wrote in message
news:a3**************************@posting.google.c om...
Hi,

the following sample code shows a compiler error I get trying to build
some old code with the last CL compiler (vers 13.10.3077):

//----- begin
#include <iostream>

namespace ns
{
class base
{
public:
base() {}
virtual ~base() {}
protected:
void Call() { std::cout << "OK" << std::endl; }
};

class derived : public base
{
public:
void Start()
{
typedef void (ns::base::* typeCall)(void);
typeCall fnCall;
fnCall = &ns::base::Call; // this is the line # 21
(this->*fnCall)();
}
};
}
int main()
{
ns::derived d;
d.Start();

return 0;
}
//----- end

I get the following compiler message error at line 21:

main.cpp(21): error C2248: 'ns::base::Call' : cannot access protected
member declared in class 'ns::base'

Workaround: if I remove the ampersand all works fine.

I like to know if the line # 21 is really illegal.

thanks.
Marco.

Nov 16 '05 #2
marco_segurini wrote:
Thank you very much.

A last question: why

fnCall = /*&*/ns::base::Call; // line # 21 without ampersand

compile fine?


According to the standard, it should not. It's an MS extension to accept
it. Try compiling with -Za & see if it's then flagged as an error.

-cd
Nov 16 '05 #3
Jasper Kent wrote:
I wouldn't like to trawl through the standard on this one, but I
suspect that the error is correct.

A derived class method is only allowed to access protected members in
base when base is acting as derived's base class. Thus:

class derived : public base
{
public:
void Start()
{
derived objA;
objA.Call (); // Compiles OK

base objB; // Or a different derived class
objB.Call (); // Compiler error
}
};

So to make your code compile, replace:

fnCall = &ns::base::Call;

with

fnCall = &ns::derived::Call;
Correct.

which works even though Call () is not overridden in derived.

If you do have a derived implementation of Call, and you still want
base::Call, then

fnCall = &ns::derived::base::Call;


This should produce the same error as the original - ns::base::Call is not
accessible through a pointer or reference to ns::base.

-cd
Nov 16 '05 #4

"Carl Daniel [VC++ MVP]" <cp******@nospam.mvps.org> wrote in message
news:OS**************@tk2msftngp13.phx.gbl...
Jasper Kent wrote:
I wouldn't like to trawl through the standard on this one, but I
suspect that the error is correct.

A derived class method is only allowed to access protected members in
base when base is acting as derived's base class. Thus:

class derived : public base
{
public:
void Start()
{
derived objA;
objA.Call (); // Compiles OK

base objB; // Or a different derived class
objB.Call (); // Compiler error
}
};

So to make your code compile, replace:

fnCall = &ns::base::Call;

with

fnCall = &ns::derived::Call;
Correct.

which works even though Call () is not overridden in derived.

If you do have a derived implementation of Call, and you still want
base::Call, then

fnCall = &ns::derived::base::Call;


This should produce the same error as the original - ns::base::Call is not
accessible through a pointer or reference to ns::base.


Well it compiles fine on VC++ v7.

-cd

Nov 16 '05 #5
If it's good enough for you, a VC++ MVP, then why isn't it good enough for
VC++ compiler itself?

"Carl Daniel [VC++ MVP]" <cp******@nospam.mvps.org> wrote in message
news:ug**************@TK2MSFTNGP12.phx.gbl...
Jasper Kent wrote:
"Carl Daniel [VC++ MVP]" <cp******@nospam.mvps.org> wrote in message
news:OS**************@tk2msftngp13.phx.gbl...

This should produce the same error as the original - ns::base::Call
is not accessible through a pointer or reference to ns::base.


Well it compiles fine on VC++ v7.


The gold standard of the Standard, Comeau, rejects it though. Without
spending a lot of time wading through the turgid verbiage of the standard,
that's good enough for me. It's definitely a dark corner though.

-cd

Nov 16 '05 #6

--------------------
From: ma***********@virgilio.it (marco_segurini)
Newsgroups: microsoft.public.dotnet.languages.vc
Subject: Get parent class function pointer
Date: 8 Sep 2003 02:55:54 -0700
Organization: http://groups.google.com/
Lines: 53
Message-ID: <a3**************************@posting.google.com >
NNTP-Posting-Host: 62.110.81.102
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: posting.google.com 1063014955 12167 127.0.0.1 (8 Sep 2003 09:55:55 GMT)X-Complaints-To: gr**********@google.com
NNTP-Posting-Date: 8 Sep 2003 09:55:55 GMT
Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!news-out.cwix.com!newsfeed.cwix.co
m!newsfeed.frii.net!newsfeed.frii.net!140.99.99.19 4.MISMATCH!newsfeed1.easyn
ews.com!easynews.com!easynews!sn-xit-02!sn-xit-04!sn-xit-06!sn-xit-05!sn-xit
-09!supernews.com!postnews1.google.com!not-for-mailXref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.vc:28042
X-Tomcat-NG: microsoft.public.dotnet.languages.vc

Hi,

the following sample code shows a compiler error I get trying to build
some old code with the last CL compiler (vers 13.10.3077):

//----- begin
#include <iostream>

namespace ns
{
class base
{
public:
base() {}
virtual ~base() {}
protected:
void Call() { std::cout << "OK" << std::endl; }
};

class derived : public base
{
public:
void Start()
{
typedef void (ns::base::* typeCall)(void);
typeCall fnCall;
fnCall = &ns::base::Call; // this is the line # 21
(this->*fnCall)();
}
};
}
int main()
{
ns::derived d;
d.Start();

return 0;
}
//----- end

I get the following compiler message error at line 21:

main.cpp(21): error C2248: 'ns::base::Call' : cannot access protected
member declared in class 'ns::base'

Workaround: if I remove the ampersand all works fine.

I like to know if the line # 21 is really illegal.

thanks.
Marco.


Here's the reason from the ISO Standard:

[class.protected] 11.5 Protected member access
1 When a friend or a member function of a derived class references a
protected nonstatic member function or
protected nonstatic data member of a base class, an access check applies in
addition to those described earlier
in clause 11.102) Except when forming a pointer to member (5.3.1), the
access must be through a
pointer to, reference to, or object of the derived class itself (or any
class derived from that class) (5.2.5). If
the access is to form a pointer to member, *** the nested-name-specifier
shall name the derived class (or any
class derived from that class). ***

Note the part marked with "***". This is what the compiler is complaining
about.

--
Tanveer Gani, Microsoft Visual C++ Team
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm
Nov 16 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by Paul | last post: by
16 posts views Thread by Suzanne Vogel | last post: by
9 posts views Thread by Martin Herbert Dietze | last post: by
2 posts views Thread by dannielum | last post: by
reply views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.