473,725 Members | 2,281 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

accessing subclass members via a base pointer?

Me
I need to be able to acces non-virtual members of sublcasses via a
base class pointer...and without the need for an explicit type cast.
I thought a pure virtual getPtr() that acts as a type cast would solve
the problem, but it appears not to.

I need this functionality to make object serialization a reality. Having
to explicitly cast each deserialized object to its original type defeats
the purpose of my serializing the blasted things in the first place. The
serialization functions all work at this point but the deserialized object,
accessible via a base class pointer, must allow for an "implicit" cast to
the correct subclass. See below...
#include <iostream>
#include <iomanip>

struct base {
virtual base* getPtr()=0;
};
struct subclass: public base {
subclass* getPtr() { return this; }
const char* isA() { return "subclass"; }
};

using namespace std;
int main(int argc, char** argv) {
base* p=new subclass();

// $ g++ test.cc # using gcc 4.1.2 and glibc 2.5.18
// test.cc: In function 'int main()':
// test.cc:19: error: 'struct base' has no member named 'classname'
cout << p->getPtr()->isA() << endl;

return 0;
};

I would EXPECT p->getPtr() to do a correct type cast of the pointer so
that ->isA() is called with a pointer of the correct type, but that's not
happening...WTF !?

Oct 31 '07 #1
6 4596
On Oct 30, 4:59 pm, Me <no...@all.comw rote:
I need to be able to acces non-virtual members of sublcasses via a
base class pointer...and without the need for an explicit type cast.
I thought a pure virtual getPtr() that acts as a type cast would solve
the problem, but it appears not to.

I need this functionality to make object serialization a reality.
I think you're stuck. Why not make a virtual SerializeIt() method
instead?

See below for details
#include <iostream>
#include <iomanip>

struct base {
virtual base* getPtr()=0;};

struct subclass: public base {
subclass* getPtr() { return this; }
const char* isA() { return "subclass"; }

};
getPtr() is not virtual so it is statically bound based on the type,
which is known at compile time.
using namespace std;
int main(int argc, char** argv) {
base* p=new subclass();

p has type "pointer to base"
cout << p->getPtr()->isA() << endl;
Since p is a "base" and getPtr() is not virtual, I would expect the
compiler to generate a call to base::getPtr(). Since base doesn't
have an isA() method in this code, I'd expect it to fail. Does it
actually compile, or does your real code have a base::isA() method?
return 0;

};

I would EXPECT p->getPtr() to do a correct type cast of the pointer so
that ->isA() is called with a pointer of the correct type, but that's not
happening...WTF !
Oct 31 '07 #2
On Wed, 31 Oct 2007 05:11:31 +0000, Tim H wrote:
>
I think you're stuck. Why not make a virtual SerializeIt() method
instead?
Serialization is not a problem and that part works. The problem is
that deserialization is pretty much useless if I still have to do
an explicit cast from a base pointer type back to the correct
subclass in the heirarchy upon object reconstruction.
>struct base {
virtual base* getPtr()=0;};

struct subclass: public base {
subclass* getPtr() { return this; }
const char* isA() { return "subclass"; }

};

getPtr() is not virtual so it is statically bound based on the type,
which is known at compile time.
If you look closely you will see that getPtr() is declared virtual in the
base class and the correct sublcass::getPt r() is being called. I verified
this by inserting an exit(0) in subclass::getPt r().

Since p is a "base" and getPtr() is not virtual, I would expect the
compiler to generate a call to base::getPtr(). Since base doesn't have
an isA() method in this code, I'd expect it to fail. Does it actually
compile, or does your real code have a base::isA() method?
see above and note that the compiler error was in the OP...the virtual
nature of getPtr() has been verified but the compiler wont recognize the
subclass* return value of getPtr() to allow access to subclass::isA() .

What I'm seeing is weird because the epxression p->getPtr() should return
a subclass* and that return type should be compatible with subclass::isA() .
Oct 31 '07 #3
On 2007-10-31 06:49, Just me wrote:
On Wed, 31 Oct 2007 05:11:31 +0000, Tim H wrote:
>>
I think you're stuck. Why not make a virtual SerializeIt() method
instead?

Serialization is not a problem and that part works. The problem is
that deserialization is pretty much useless if I still have to do
an explicit cast from a base pointer type back to the correct
subclass in the heirarchy upon object reconstruction.
>>struct base {
virtual base* getPtr()=0;};

struct subclass: public base {
subclass* getPtr() { return this; }
const char* isA() { return "subclass"; }

};

getPtr() is not virtual so it is statically bound based on the type,
which is known at compile time.

If you look closely you will see that getPtr() is declared virtual in the
base class and the correct sublcass::getPt r() is being called. I verified
this by inserting an exit(0) in subclass::getPt r().
What Tim meant was that you are not allowed to change the return type of
a virtual function. However, returning a type that is a subtype of the
original function's is allowed, but that does not help you.
>Since p is a "base" and getPtr() is not virtual, I would expect the
compiler to generate a call to base::getPtr(). Since base doesn't have
an isA() method in this code, I'd expect it to fail. Does it actually
compile, or does your real code have a base::isA() method?

see above and note that the compiler error was in the OP...the virtual
nature of getPtr() has been verified but the compiler wont recognize the
subclass* return value of getPtr() to allow access to subclass::isA() .

What I'm seeing is weird because the epxression p->getPtr() should return
a subclass* and that return type should be compatible with subclass::isA() .
No, the pointer p is of of type base*, that means that the function
called is base's getPtr() (but the code that is executed is one in
subclass) which means that the type of the pointer that is returned from
getPtr() have the type declared in base's getPtr(), namely base*.

With a pointer to base you can only call base's functions. Though if
they are virtual and the actual type of the object pointed to is a
derived type then the implementation in the derived type will be used.
But it is still the base's function that was called. What you can do is
make isA() a virtual function in base, and use the value returned to
dynamic_cast() the pointer to the correct subtype.

--
Erik Wikström
Oct 31 '07 #4
Me
On Wed, 31 Oct 2007 08:21:04 +0000, Noone wrote:
No, the pointer p is of of type base*, that means that the function
called is base's getPtr() (but the code that is executed is one in
subclass) which means that the type of the pointer that is returned from
getPtr() have the type declared in base's getPtr(), namely base*.

With a pointer to base you can only call base's functions. Though if
they are virtual and the actual type of the object pointed to is a
derived type then the implementation in the derived type will be used.
But it is still the base's function that was called. What you can do is
make isA() a virtual function in base, and use the value returned to
dynamic_cast() the pointer to the correct subtype.
then it is still an exercise in futility because the whole purpose was to
avoid having to do an explicit cast through some switch() statement...so
unless dynamic_cast<ta kes runtime computed values as its template
argument, then all is for not...

regarding changing the return type of a virtual: the compiler should
warn me of this if it is not allowed...The assumption was that it is
allowed since there was no compiler error there and the correct
getPtr() virtual was being executed.
thanks.
Oct 31 '07 #5
On 2007-10-31 17:39, Me wrote:
On Wed, 31 Oct 2007 08:21:04 +0000, Noone wrote:
>No, the pointer p is of of type base*, that means that the function
called is base's getPtr() (but the code that is executed is one in
subclass) which means that the type of the pointer that is returned from
getPtr() have the type declared in base's getPtr(), namely base*.

With a pointer to base you can only call base's functions. Though if
they are virtual and the actual type of the object pointed to is a
derived type then the implementation in the derived type will be used.
But it is still the base's function that was called. What you can do is
make isA() a virtual function in base, and use the value returned to
dynamic_cast () the pointer to the correct subtype.

then it is still an exercise in futility because the whole purpose was to
avoid having to do an explicit cast through some switch() statement...so
unless dynamic_cast<ta kes runtime computed values as its template
argument, then all is for not...
No, it does not.
regarding changing the return type of a virtual: the compiler should
warn me of this if it is not allowed...The assumption was that it is
allowed since there was no compiler error there and the correct
getPtr() virtual was being executed.
As I said, it is not allowed. But in your case you did not actually
change the return type as much as being a little more specific about it.
The getPtr in base returned a pointer to base, while the getPtr() in
subclass returned a pointer to a subclass. And since a pointer to a
subclass is (or rather is convertible to) a pointer to base the return
type was not changed. And you were correct in assuming the correct
getPtr() was executed.

--
Erik Wikström
Oct 31 '07 #6
On Oct 31, 9:21 am, Erik Wikström <Erik-wikst...@telia. comwrote:
On 2007-10-31 06:49, Just me wrote:
On Wed, 31 Oct 2007 05:11:31 +0000, Tim H wrote:
[...]
If you look closely you will see that getPtr() is declared
virtual in the base class and the correct sublcass::getPt r()
is being called. I verified this by inserting an exit(0) in
subclass::getPt r().
What Tim meant was that you are not allowed to change the
return type of a virtual function. However, returning a type
that is a subtype of the original function's is allowed, but
that does not help you.
What you meant is that returning a pointer or a reference to a
derived type when the function in the base class returns a
pointer or reference to a base is legal. It's called co-variant
return. But of course, the type of the pointer which gets used
at the call site is determined statically. If the static type
is base*, it can only be used to call functions declared in
base. Regardless of what the base* really points to.
Since p is a "base" and getPtr() is not virtual, I would
expect the compiler to generate a call to base::getPtr().
Since base doesn't have an isA() method in this code, I'd
expect it to fail. Does it actually compile, or does your
real code have a base::isA() method?
see above and note that the compiler error was in the
OP...the virtual nature of getPtr() has been verified but
the compiler wont recognize the subclass* return value of
getPtr() to allow access to subclass::isA() .
What I'm seeing is weird because the epxression p->getPtr()
should return a subclass* and that return type should be
compatible with subclass::isA() .
No, the pointer p is of of type base*, that means that the
function called is base's getPtr() (but the code that is
executed is one in subclass)
Only if the function is virtual. Basically, the entire call
sequence is first resolved (overloading, etc.) statically.
Then, if and only if the chosen function is declared virtually,
the compiler will invoke the function of the most derived class.
But before any such considerations, the compiler must see a
declaration of the function. Using purely static analysis.

FWIW, this is a standard behavior of a statically typed
language. It's not specific to C++: Java, C# and I believe
Ada95 and Eiffel all have the same behavior. If you want
something different, you need a fully dynamically typed
language, like Lisp or Smalltalk. Which has other
disadvantages: whatever language you choose represents a
compromise between safety and flexibility (with C++ leaning
very, very strongly to the side of safety).
which means that the type of the pointer that is returned from
getPtr() have the type declared in base's getPtr(), namely
base*.
With a pointer to base you can only call base's functions.
Though if they are virtual and the actual type of the object
pointed to is a derived type then the implementation in the
derived type will be used. But it is still the base's
function that was called.
I know what you're trying to say, but that sounds a bit
confusing, since of course, you don't actually call the function
in base---if it is pure virtual, there is no function to call.
I prefer to explain it in terms of compile time "resolution "
(given that we already have to term "overload resolution"). The
compiler must first choose which function to call, statically;
how can it know if the function is virtual until it has choosen
it?

The actual "resolution " is a fairly complex process, involving
name lookup, including ADL, then type deduction on template
parameters, and finally overload resolution. Having "resolved"
the function, the compiler then does things like access checks
(private, etc.), and only after all this does it consider
whether the function is virtual or not, and either call the
function in the statically declared type or the one in the
dynamic type.
What you can do is make isA() a virtual function in base, and
use the value returned to dynamic_cast() the pointer to the
correct subtype.
There are a number of possible solutions, but since we don't
really know the problem...

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 1 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
2421
by: Gerry Sutton | last post by:
Hi All! I have noticed a strange behavior when using a constant identifier to initialize an instance list variable in a base class and then trying to modifying the list in subclasses by using either the list.extend method or even by having the subclass create a whole new list in the variable. The following example illustrates the situation.
2
2309
by: Steven T. Hatton | last post by:
I find the surprising. If I derive Rectangle from Point, I can access the members of Point inherited by Rectangle _IF_ they are actually members of a Rectangle. If I have a member of type Point in Rectangle, the compiler tells me Point::x is protected. I would have expected Rectangle to see the protected members of any Point. Compiling the following code give me this error: g++ -o rectangle main.cc main.cc: In member function `size_t...
4
1578
by: pramod8378 | last post by:
#include <iostream.h> class Simple { public : void memfunction() { cout << "Hello I am in memFunction" ; } }; Simple *objSimple ;
6
2617
by: harry | last post by:
Hi ppl I have a question about memory layout of a class. Consider the code below: class Base1 { virtual void f() { cout << "Base1::f" << endl; } virtual void g() { cout << "Base1::g" << endl; } }; class Drive : public Base1{
14
1877
by: Glen Dayton | last post by:
While looking at some old code I ran across a snippet that increments a pointer to access different members of a structure: .... struct Badness { std::string m_begin; std::string m_param1; std::string m_param2; std::string m_end;
9
4684
by: vilarneto | last post by:
Hello everyone, Today I started to use template specializations in a project and suddenly faced a curious problem. Following is a complete example that shows the situation: ---------- class A { };
3
2398
by: orkonoid | last post by:
Hello, I am having trouble with a Polymorphism issue using container classes. I have a longwinded and shortwinded version of my question: Shortwinded version: How can I store base class objects in a container class like a vector or list while still being able to access the individual subclass (virtual) functions? In my program, it is as if the functions aren't virtual. Longwinded version:
6
8159
by: Bhawna | last post by:
I am into c++ code maintenance for last 3-4 years but recently I am put into design phase of a new project. Being a small comapany I dont have enough guidance from seniors. Currently I am into a situation where I am implementing base class functions by including a pointer to subclass member in base class. Reason being functionality is common for subclasses but the members are common within subclass only (static member of subclass) but...
0
8889
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8752
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9257
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9179
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9116
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6702
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6011
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4519
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
3
2157
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.