Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Problem with a friend declaration when migrating project (http://www.velocityreviews.com/forums/t951277-problem-with-a-friend-declaration-when-migrating-project.html)

Uwe Kotyczka 08-23-2012 10:39 AM

Problem with a friend declaration when migrating project
 
When migrationg a project from Visual Studio 2003 to Visual Studio
2010 I found a problem with a friend declarition. To illustratte it
I wrote a small sample programm (complete code see below).

I have two classes, class A and class Property. Class Property has
an assignment operator: const Property& operator=(const double
dValue);

Class A has a member variable of type Property. Only in one
specific function of class A, say A::DoSetProperty, I want
that the property can be changed. Therefore I declared the
assignment operator of class Property private and made
A::DoSetProperty a friend function of class Property.

That worked fine in Visual Studio 2003, however when migrating
to Visual Studio 2010 the compiler complains that it can't
see the friend declaration of A::DoSetProperty, because
A::DoSetProperty is protected in class A.

As a workaround I can either make A::DoSetProperty public
(which is not what I want to do) or declare the complete
class A as a friend of class Property (which I do not wish
to do either). Or I make the assignment operator public,
but then it can be called in any function of class A and
not only in A::DoSetProperty.

What would be the best solution? I would prefer a clear design
over a workaround.

Here comes the complete sample code:


#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>

////////////////////////////////////////////////////////////
class Property;

////////////////////////////////////////////////////////////
class A
{
public:
A();
virtual ~A();
void SetProperty(const double dValue);
protected:
void DoSetProperty(const double dValue);
private:
Property* m_pProperty;
};

////////////////////////////////////////////////////////////
class Property
{
friend void A::DoSetProperty(const double dValue);
public:
Property();
virtual ~Property();
int GetValue() const;
private:
const Property& operator=(const double dValue);
int m_nValue;
};

////////////////////////////////////////////////////////////
A::A()
{
m_pProperty = new Property();
}

A::~A()
{
if (m_pProperty)
delete m_pProperty;
}
void A::SetProperty(const double dValue)
{
DoSetProperty(dValue);
}

void A::DoSetProperty(const double dValue)
{
if (m_pProperty)
*m_pProperty = dValue;
}

////////////////////////////////////////////////////////////
Property::Property()
{
m_nValue = -1;
}

Property::~Property()
{
}

int Property::GetValue() const
{
return m_nValue;
}

const Property& Property::operator=(const double dValue)
{
m_nValue = static_cast<int>(dValue);
return *this;
}

////////////////////////////////////////////////////////////
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
A testA;
testA.SetProperty(5.5);

return 0;
}

Victor Bazarov 08-23-2012 12:01 PM

Re: Problem with a friend declaration when migrating project
 
On 8/23/2012 6:39 AM, Uwe Kotyczka wrote:
> I have two classes, class A and class Property. Class Property has
> an assignment operator: const Property& operator=(const double
> dValue);
>
> Class A has a member variable of type Property. Only in one
> specific function of class A, say A::DoSetProperty, I want
> that the property can be changed. Therefore I declared the
> assignment operator of class Property private and made
> A::DoSetProperty a friend function of class Property.
>
> That worked fine in Visual Studio 2003, however when migrating
> to Visual Studio 2010 the compiler complains that it can't
> see the friend declaration of A::DoSetProperty, because
> A::DoSetProperty is protected in class A.
>
> As a workaround I can either make A::DoSetProperty public
> (which is not what I want to do) or declare the complete
> class A as a friend of class Property (which I do not wish
> to do either). Or I make the assignment operator public,
> but then it can be called in any function of class A and
> not only in A::DoSetProperty.
>
> What would be the best solution? I would prefer a clear design
> over a workaround.


You have a chicken and egg design problem. On one hand, your property
requires friendship to use its operator=. So, you solve it by making
the user of operator= (your 'A::DoSetProperty' function) a friend of
Property. On the other hand, access to 'A::DoSetProperty' is blocked as
well, so you need to give your Property some way to access it. You can
make Property a *derived class* of A, but that's not right, is it?

Declare class Property a friend of A. After all, in order to see A's
private (and protected) parts, Property has to be either a friend or a
relative. Another possibility is to get rid of the extra indirection
(the 'A::DoSetProperty' nonsense), leave only 'A::SetProperty' around
and let *that member* be a friend of Property. What's the reason to
have that 'DoSetProperty', anyway?

V
--
I do not respond to top-posted replies, please don't ask


All times are GMT. The time now is 04:51 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.