Problem with a friend declaration when migrating project

Discussion in 'C++' started by Uwe Kotyczka, Aug 23, 2012.

  1. Uwe Kotyczka

    Uwe Kotyczka Guest

    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::eek:perator=(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;
    }
    Uwe Kotyczka, Aug 23, 2012
    #1
    1. Advertising

  2. 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
    Victor Bazarov, Aug 23, 2012
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Felix
    Replies:
    1
    Views:
    1,005
    simon
    Nov 26, 2005
  2. Hrvoje Vrbanc
    Replies:
    2
    Views:
    1,322
    =?Utf-8?B?UmFodWwgU29uaQ==?=
    Nov 30, 2005
  3. Alexander Stippler

    nested classes and friend declaration

    Alexander Stippler, Jul 2, 2003, in forum: C++
    Replies:
    1
    Views:
    379
    Victor Bazarov
    Jul 2, 2003
  4. Klaus
    Replies:
    3
    Views:
    1,040
    Klaus
    Mar 31, 2008
  5. Peter
    Replies:
    2
    Views:
    265
    Öö Tiib
    Jun 6, 2013
Loading...

Share This Page