Reputation: 233
I'm currently learning C++, and this time I was messing with pointers, and studying the this
pointer and polymorphism. My question is, is the conversion below safe, I know that basically I can access m_uConnectedUsers
directly from CUser
class because of 'public', but I may find an occasion where it will be needed, and I would like to know the opinion of you professionals about it.
#include <windows.h>
#include <iostream>
using namespace std;
class CUserCounter
{
public:
CUserCounter();
virtual ~CUserCounter(){};
BOOL m_bEmpty;
u_long m_uConnectedUsers;
};
CUserCounter::CUserCounter()
{
m_bEmpty = TRUE;
m_uConnectedUsers = 0;
}
class CUser : public CUserCounter
{
public:
CUser(LPCTSTR szName, BOOL bConnected, BOOL bChatting = FALSE );
virtual ~CUser(){};
BOOL m_bConnected;
BOOL m_bIsChatting;
TCHAR szCharName[32];
bool IncreaseMoverMeter( unsigned uMeters );
};
CUser::CUser( LPCTSTR szName, BOOL bConnected, BOOL bChatting )
{
if( szName )
{
if( strlen( szName ) > 30 )
strcpy( szCharName, "Invalid" );
else
strcpy( szCharName, szName );
}
m_bConnected = bConnected;
m_bIsChatting = bChatting;
}
bool CUser::IncreaseMoverMeter( unsigned uMeters )
{
//is it safe? how does it works
CUserCounter* pUserCounter = (CUserCounter*)this;
if( pUserCounter )
{
pUserCounter->m_uConnectedUsers++;
return true;
}
return false;
}
int main( int argc, char *argv[] )
{
CUser *pUser = new CUser( "Jonh", FALSE );
std::cout << pUser->IncreaseMoverMeter( 4 );
system("pause>nul");
return EXIT_SUCCESS;
}
Upvotes: 0
Views: 568
Reputation: 9206
In my opinion such conversion is not only unnecessary but also inelegant. As someone said it's obvious that if you inherit from some class you have some fields/method available. You not only write some needless code, but also make your methods less readable and more difficult to maintain. The compiler would probably optimize such code and remove additional instructions so there might be no efficiency costs (but it's only my assumption). I strongly believe that when you think that this
conversion is necessary there is a great probability that you should rethink your implementation once again.
Upvotes: 0
Reputation: 308206
I'd like to discuss a larger issue than the one explicitly in the question.
You have CUser deriving from CUserCounter. This seems like a mistake, as a user is not a counter. In this case you should have an has-a relationship - the CUser object should contain a CUserCounter object, not be one.
To answer the question, a derived class can access any members of a base class that it wants. No casting required, and in fact casting can hide some nasty problems - avoid it unless absolutely necessary.
Upvotes: 3
Reputation: 28762
Ususally it is not recommended to put member variables in the public. Instead make them private and provide a public getter and/or setter method.
If you have to access the variable from derived classes, make it protected
The reason for this is that member variables represent the state of the object, and allowing direct modification is not recommended as it allows changes to the state in ways that breaks the underlying logic of the class (think of a String class: if you can directly modify the variable holding the cache of the size of the string that can wreak havok on further use of the object if the character array is not re-sized accordingly as well)
As for the this
pointer: in most contexts you do not need to explicitly use it, its use can be decuced from the context. However, if you have a member variable and a parameter in a member function with the same name, the parameter will hide the member variable, and you will have to use this
to be able to access it. (Similar effect comes to play when a derived class's member function hides the parent's function declarations)
You can access protected and public members of a class's parent class as well via this
, but as noted above you usually do not need to use it. Also, no conversion to (pointer to) the parent's type is needed in these cases
Upvotes: 2
Reputation: 258618
Yes, it's safe, but also not necessary. :)
The conversion is implicit, so no need to cast.
CUser
is a CUserCounter
(at least in your design), so a pointer to a CUser
is also a pointer to a CUserCounter
.
Upvotes: 6