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;
}