Good afternoon,

I am having a hard time understanding how to use the "Friend" function prototype and the Friend function to move my rectangle. My programm with just the constructors, the properties and the functions work corectly until I put the "friend" function prototype and function.
I would so much appreciate your help in getting ride of my error messages. The purpose of the "friend" is to move a rectangle from one location to another.

Thank you for your time,

John

My code:

#include "stdafx.h"  
using namespace System;  
  
  
ref class Rectangle   // Class definition at global scope    
{  
 //private:  
  int Left;  
  int Top;   
  int Right;  
  int Bottom;  
   
public:   
  
  //1st Constructor  
  Rectangle() ; 
 
  //2nd Constructor  
  Rectangle(int ,int ,int , int ) ; 
 
  //Defining the property for obtaining the LeftValue  
   property int LeftValue  
   {  
           int get ()  
           {  
           return Left;  
           }  
           void set(int value) { Left = value; }  
   }  
  
   virtual String^ ToStringLeft() override   
   { return Left + L"Left";}  
  
 //Defining the property for obtaining the TopValue   
    property int TopValue  
   {  
           int get ()  
           {  
           return Top;  
           }  
           void set(int value) { Top = value; }  
   }  
  
   virtual String^ ToStringTop() override   
   { return Top + L"Top";}  
    
 //Defining the property for obtaining the RightValue  
    property int RightValue  
   {  
           int get ()  
           {  
           return Right;  
           }  
           void set(int value) { Right = value; }  
   }  
  
   virtual String^ ToStringRight() override   
   { return Right + L"Right";}  
 
 //Defining the property for obtaining the BottomValue  
    property int BottomValue  
   {  
           int get ()  
           {  
           return Bottom;  
           }  
           void set(int value) { Bottom = value; }  
   }  
  
   virtual String^ ToStringBottom() override   
   { return Bottom + L"Bottom";} 
 
//Function of Length 
long Length()  
{ 
        return (Right - Left);   
}  
 
//Function of Width 
long Width()  
{ 
        return (Bottom - Top);   
}  
 
//function of area 
long area()  
{ 
        return (Right - Left)*(Bottom - Top); 
} 
         
//Friend function prototype  
        friend void MoveRect(Rectangle& aRect, int x, int y); 
};  
 
 
Rectangle::Rectangle ()   
{  
            Console::WriteLine(L"Rectangle Constructor with no parameters called."); 
        Left = 3;  
        Top = 4;  
        Right = 7;  
        Bottom = 8;  
}  
  
Rectangle::Rectangle(int lt, int tp, int rt, int bm)   
{  
        Console::WriteLine(L"Rectangle Constructor with four parameters called."); 
        Left = lt;  
        Top = tp;  
        Right = rt;  
        Bottom = bm;  
}  
 
// Friend function to move rectangle 
void MoveRect(Rectangle& aRect, int x, int y)  
{  
        int Length = aRect.Right - aRect.Left;    // Get length of rectangle  
        int Width = aRect.Bottom - aRect.Top;     // Get width of rectangle  
  
        aRect.Left = x;                           // Set top left point  
        aRect.Top = y;                            // to new position  
        aRect.Right = x + Length;                 // Get bottom right point as  
        aRect.Bottom = y + Width;                 // increment from new position  
} 
 
int main(array<System::String ^> ^args)  
{  
        Rectangle Rect(2,8,80,120);    //Declaring Rect 
        Rectangle Rect2;  
 
        Rect2 = Rect;  
        MoveRect(Rect2, 10, 30);  
  
{     
        //Displaying Rect values  
        Console::WriteLine(L"Displaying Rect values");   
        Console::WriteLine(L"Rect left Value: = {0}",Rect.LeftValue);  
        Console::WriteLine(L"Rect top Value: = {0}",Rect.TopValue); 
        Console::WriteLine(L"Rect Right Value: = {0}",Rect.RightValue); 
        Console::WriteLine(L"Rect Bottom Value: = {0}",Rect.BottomValue); 
        Console::WriteLine(L"Rect area  = {0}",Rect.area()); 
        Console::WriteLine(L"Rect Length = {0}",Rect.Length()); 
        Console::WriteLine(L"Rect Width = {0}",Rect.Width()); 
        Console::WriteLine(L" ");   
 
        //Display values for Rect2 after the move 
        Console::WriteLine(L"Displaying the Rect2 values after the move:"); 
        Console::WriteLine(L"Rect2 area after move = {0}",Rect2.area()); 
        Console::WriteLine(L"Rect2 Left after move = {0}",Rect2.LeftValue()); 
        Console::WriteLine(L"Rect2 Top Value after move = {0}",Rect2.TopValue()); 
        Console::WriteLine(L"Rect2 Length after move = {0}",Rect2.Length()); 
        Console::WriteLine(L"Rect2 Width after move = {0}",Rect2.Width()); 
        Console::WriteLine(L" "); 
 
    return 0;  
}  
  
}

Like the error says you can not use the friend keyword in a managed type (manged C++ has delegates and events to get round that).

Why can you just make your MoveRect function a class member?

I tried but I may not know how to. In order to make it part of the class I should be able to jsut move down the "}; " on line 93 down to line 125 right?
I did but it didn't work?

no you would remove the first parameter as well and operate directly on all the class members just like your other member functions.

Please forgive my newest but could you please show me or tell me what line number we are speaking about. I do not know what parameter you are speaking about?

Line 115 re-write

// Friend function to move rectangle
void MoveRect(Rectangle& aRect, int x, int y)
{
    ... function code snipped 
}

as

// Member function to move rectangle
void Rectangle::MoveRect(int x, int y)
{
    ... function code snipped 
}

Thank you for working with me on this.

I did the change of code but the intellisense wasn't showing me anything as I was typing the code you gave me and I got 24 errors when I tried to run it.

The change I did was to move the "};" from line 93 to 125, and the line 115 as you showed me.

Thank you for your help

Just to name a few errors:
.\dani2.cpp(92) : error C3699: '&' : cannot use this indirection on type 'Rectangle' compiler replacing '&' with '^' to continue parsing

.\dani2.cpp(92) : error C3809: 'Rectangle': a managed type cannot have any friend functions/classes/interfaces

.\dani2.cpp(31) : warning C4490: 'override' : incorrect use of override specifier; 'Rectangle::ToStringLeft' does not match a base ref class method 'new' or 'override' are only allowed when a matching base method from a ref class exists

don't move the } at line 93 just change line 92 from friend void MoveRect(Rectangle& aRect, int x, int y); to void MoveRect(int x, int y);

I thought I would repost the changed code because I must be missing something somewhere because it is giving me a lots of error codes.

Changed source code:

#include "stdafx.h"  
using namespace System;  
  
  
ref class Rectangle   // Class definition at global scope    
{
 //private:  
  int Left;  
  int Top;   
  int Right;  
  int Bottom;  
   
public:   
  
  //1st Constructor  
  Rectangle() ; 
 
  //2nd Constructor  
  Rectangle(int ,int ,int , int ) ; 
 
  //Defining the property for obtaining the LeftValue  
   property int LeftValue  
   {  
           int get ()  
           {  
           return Left;  
           }  
           void set(int value) { Left = value; }  
   }  
  
   virtual String^ ToStringLeft() override   
   { return Left + L"Left";}  
  
 //Defining the property for obtaining the TopValue   
    property int TopValue  
   {  
           int get ()  
           {  
           return Top;  
           }  
           void set(int value) { Top = value; }  
   }  
  
   virtual String^ ToStringTop() override   
   { return Top + L"Top";}  
    
 //Defining the property for obtaining the RightValue  
    property int RightValue  
   {  
           int get ()  
           {  
           return Right;  
           }  
           void set(int value) { Right = value; }  
   }  
  
   virtual String^ ToStringRight() override   
   { return Right + L"Right";}  
 
 //Defining the property for obtaining the BottomValue  
    property int BottomValue  
   {  
           int get ()  
           {  
           return Bottom;  
           }  
           void set(int value) { Bottom = value; }  
   }  
  
   virtual String^ ToStringBottom() override   
   { return Bottom + L"Bottom";} 
 
//Function of Length 
long Length()  
{ 
        return (Right - Left);   
}  
 
//Function of Width 
long Width()  
{ 
        return (Bottom - Top);   
}  
 
//function of area 
long area()  
{ 
        return (Right - Left)*(Bottom - Top); 
} 
         
//New Changes
  void Rectangle::MoveRect(int x, int y);
 };

Rectangle::Rectangle ()   
{  
            Console::WriteLine(L"Rectangle Constructor with no parameters called."); 
        Left = 3;  
        Top = 4;  
        Right = 7;  
        Bottom = 8;  
}  
  
Rectangle::Rectangle(int lt, int tp, int rt, int bm)   
{  
        Console::WriteLine(L"Rectangle Constructor with four parameters called."); 
        Left = lt;  
        Top = tp;  
        Right = rt;  
        Bottom = bm;  
}  
 
// new changes
void Rectangle::MoveRect(int x, int y)

{  
        int Length = aRect.Right - aRect.Left;    // Get length of rectangle  
        int Width = aRect.Bottom - aRect.Top;     // Get width of rectangle  
  
        aRect.Left = x;                           // Set top left point  
        aRect.Top = y;                            // to new position  
        aRect.Right = x + Length;                 // Get bottom right point as  
        aRect.Bottom = y + Width;                 // increment from new position  
} 
 


int main(array<System::String ^> ^args)  
{  
        Rectangle Rect(2,8,80,120);    //Declaring Rect 
        Rectangle Rect2;  
 
        Rect2 = Rect;  
        MoveRect(Rect2, 10, 30);  
  
{     
        //Displaying Rect values  
        Console::WriteLine(L"Displaying Rect values");   
        Console::WriteLine(L"Rect left Value: = {0}",Rect.LeftValue);  
        Console::WriteLine(L"Rect top Value: = {0}",Rect.TopValue); 
        Console::WriteLine(L"Rect Right Value: = {0}",Rect.RightValue); 
        Console::WriteLine(L"Rect Bottom Value: = {0}",Rect.BottomValue); 
        Console::WriteLine(L"Rect area  = {0}",Rect.area()); 
        Console::WriteLine(L"Rect Length = {0}",Rect.Length()); 
        Console::WriteLine(L"Rect Width = {0}",Rect.Width()); 
        Console::WriteLine(L" ");   
 
        //Display values for Rect2 after the move 
        Console::WriteLine(L"Displaying the Rect2 values after the move:"); 
        Console::WriteLine(L"Rect2 area after move = {0}",Rect2.area()); 
        Console::WriteLine(L"Rect2 Left after move = {0}",Rect2.LeftValue()); 
        Console::WriteLine(L"Rect2 Top Value after move = {0}",Rect2.TopValue()); 
        Console::WriteLine(L"Rect2 Length after move = {0}",Rect2.Length()); 
        Console::WriteLine(L"Rect2 Width after move = {0}",Rect2.Width()); 
        Console::WriteLine(L" "); 
 
    return 0;  
}  
  
}

lines 117 - 123, when I said re-write the function without the parameter and operate directly on the class members that did mean that you would have re-write the function to remove references to the parameter aRect and instead use references to the member variables of the class, not that you could just change the function declaration.

Re-write the function using member variables just as all the other class member functions are using member variables.

Thank you for helping me through this Banfa.

I re-wrotte the function, sorry earlier I didn't understand correctly, but I am having challenges that I don't understand, however I progressed towards less error messages, my current errors:
- (133) : error C2582: 'operator =' function is unavailable in 'Rectangle'
- (134) : error C3861: 'MoveRect': identifier not found
- (152) : error C2064: term does not evaluate to a function taking 0 arguments
- (153) : error C2064: term does not evaluate to a function taking 0 arguments

the error on 133 is where I declare in the main "Rect2 = Rect; "
and on 134 my "MoveRect" was defined above the main.

Thanks again

Source code line 114 to 134:

void Rectangle::MoveRect(int x, int y)

{  
        int Length = Right - Left;    // Get length of rectangle  
        int Width = Bottom - Top;     // Get width of rectangle  
  
        Left = x;                           // Set top left point  
        Top = y;                            // to new position  
        Right = x + Length;                 // Get bottom right point as  
        Bottom = y + Width;                 // increment from new position  
} 

int main(array<System::String ^> ^args)  
{  
        Rectangle Rect(2,8,80,120);    //Declaring Rect 
        Rectangle Rect2;  
 
        Rect2 = Rect;  
        MoveRect(10, 30);  
  
{     
{

MoveRect needs to be called on a rectangle object because it is now a class member Rect.MoveRect(10, 30);

Thank you Banfa for such a quicke response, I see what you mean now, it has been a great learning experience.

I will be trying to understand how the moving of the rectangle now occurs and how to display it, because I have an issue with it, however I wish to spend sometime on it before asking about that.

Thanks again,

John

I'm sorry Banfa, but I really don't understand the moving of the rectangle anymore.
It used to be I declared Rect2 = Rect and then used the line 132MoveRect(Rect2, 10, 30); Then I could display its new values with line 149 and 150:

Console::WriteLine(L"Rect2 Left after move = {0}",Rect2.LeftValue());        
 Console::WriteLine(L"Rect2 Top Value after move = {0}",Rect2.TopValue());

Now with the new "MoveRect(10, 30);" on line 134 I don't see or understnad how it works. Furthermore none of the displyaing lines' intelisense function anymore. That's between line 138 to 154. It used to be I could type .....Rect.Length()); and I would see all kinds of possible selection, now there is nothing.

Thanks in advance for your help

So firstly in my above example I called MoveRect on the object Rect but is sounds like you need to do it on Rect2. Which object have you called MoveRect on?

What do you not understand about the operation of the new MoveRect? You have plenty of other member functions, it works in exactly the same way they do.

I can't help you much with the intelisense, that is a feature of the IDE you are using and I do not use MSVC on the whole. Surfice it to say that the intelisense not working correctly should not stop you programming (although it may be slightly frustrating). Often things like intelisense do not work properly in the presence of compielr errors. have you tried

Exiting you IDE and restarting it
Performing a project rebuild all

Thank you so much for your patience.
I exited the VS2008 environment entirely closing it, and re-opening it, and the intelisense came back :))

When I try to use the Rect2 by declaring it to be equal to Rect and then moving it with with line 132 "Rect.MoveRect(10, 30);", I receive this error message:
- (131) : error C2582: 'operator =' function is unavailable in 'Rectangle' "

The thing I don't understand is that I used to have this code to move Rect2:

Rect2 = Rect; 
MoveRect(Rect2, 10, 30);

Then to display my changed location:

Console::WriteLine(L"Rect2 Left after move = {0}",Rect2.LeftValue());
Console::WriteLine(L"Rect2 Top Value after move = {0}",Rect2.TopValue());

And now it is "Rect2.MoveRect(10, 30); " in the prior solution I said that Rect2 was equal to Rect and moved Rect2 to 10 and 30, and now I don't see that happening. But I have to admit I am getting a little lost.

I am posting again my whole code as it stands now.

I have to drive to work so I'll be disconnected for a little while.

Thansk again

#include "stdafx.h"  
using namespace System;  
  
  
ref class Rectangle   // Class definition at global scope    
{
 //private:  
  int Left;  
  int Top;   
  int Right;  
  int Bottom;  
   
public:   
  
  //1st Constructor  
  Rectangle() ; 
 
  //2nd Constructor  
  Rectangle(int ,int ,int , int ) ; 
 
  //Defining the property for obtaining the LeftValue  
   property int LeftValue  
   {  
           int get ()  
           {  
           return Left;  
           }  
           void set(int value) { Left = value; }  
   }  
  
   virtual String^ ToStringLeft() override   
   { return Left + L"Left";}  
  
 //Defining the property for obtaining the TopValue   
    property int TopValue  
   {  
           int get ()  
           {  
           return Top;  
           }  
           void set(int value) { Top = value; }  
   }  
  
   virtual String^ ToStringTop() override   
   { return Top + L"Top";}  
    
 //Defining the property for obtaining the RightValue  
    property int RightValue  
   {  
           int get ()  
           {  
           return Right;  
           }  
           void set(int value) { Right = value; }  
   }  
  
   virtual String^ ToStringRight() override   
   { return Right + L"Right";}  
 
 //Defining the property for obtaining the BottomValue  
    property int BottomValue  
   {  
           int get ()  
           {  
           return Bottom;  
           }  
           void set(int value) { Bottom = value; }  
   }  
  
   virtual String^ ToStringBottom() override   
   { return Bottom + L"Bottom";} 
 
//Function of Length 
long Length()  
{ 
        return (Right - Left);   
}  
 
//Function of Width 
long Width()  
{ 
        return (Bottom - Top);   
}  
 
//function of area 
long area()  
{ 
        return (Right - Left)*(Bottom - Top); 
} 
         
//New Changes
void Rectangle::MoveRect(int x, int y);
};

Rectangle::Rectangle ()   
{  
            Console::WriteLine(L"Rectangle Constructor with no parameters called."); 
        Left = 3;  
        Top = 4;  
        Right = 7;  
        Bottom = 8;  
}  
  
Rectangle::Rectangle(int lt, int tp, int rt, int bm)   
{  
        Console::WriteLine(L"Rectangle Constructor with four parameters called."); 
        Left = lt;  
        Top = tp;  
        Right = rt;  
        Bottom = bm;  
}  
 
// new changes
void Rectangle::MoveRect(int x, int y)

{  
        int Length = Right - Left;    // Get length of rectangle  
        int Width = Bottom - Top;     // Get width of rectangle  
  
        Left = x;                           // Set top left point  
        Top = y;                            // to new position  
        Right = x + Length;                 // Get bottom right point as  
        Bottom = y + Width;                 // increment from new position  
} 

int main(array<System::String ^> ^args)  
{  
        Rectangle Rect(2,8,80,120);    //Declaring Rect 
        Rectangle Rect2;  
 
        Rect2 = Rect;  
        Rect2.MoveRect(10, 30);  
  
{     
        //Displaying Rect values  
        Console::WriteLine(L"Displaying Rect values");   
        Console::WriteLine(L"Rect left Value: = {0}",Rect.LeftValue);  
        Console::WriteLine(L"Rect top Value: = {0}",Rect.TopValue); 
        Console::WriteLine(L"Rect Right Value: = {0}",Rect.RightValue); 
        Console::WriteLine(L"Rect Bottom Value: = {0}",Rect.BottomValue); 
        Console::WriteLine(L"Rect area  = {0}",Rect.area()); 
        Console::WriteLine(L"Rect Length = {0}",Rect.Length()); 
        Console::WriteLine(L"Rect Width = {0}",Rect.Width()); 
        Console::WriteLine(L" ");   
 
        //Display values for Rect2 after the move 
        Console::WriteLine(L"Displaying the Rect2 values after the move:"); 
        Console::WriteLine(L"Rect2 area after move = {0}",Rect2.area()); 
        Console::WriteLine(L"Rect2 Left after move = {0}",Rect2.LeftValue()); 
        Console::WriteLine(L"Rect2 Top Value after move = {0}",Rect2.TopValue()); 
        Console::WriteLine(L"Rect2 Length after move = {0}",Rect2.Length()); 
        Console::WriteLine(L"Rect2 Width after move = {0}",Rect2.Width()); 
        Console::WriteLine(L" "); 
 

    return 0;  
}  
  
}

For a managed C++ ref class the assignment operator(operator=) is not generated by default, if you want your class to be assignable you have to create an assignment operator.

Rect2 = Rect;
    Rect2.MoveRect(10, 30);

These lines assign Rect to Rect2 and then move Rect2 just as before, there is no change.

May I ask how I go about creating an assignment operator? I have never done that before, and I think I do not know what you are referring to.

Thank you,

John

start by reading this and relevant pages it links to.

The basic purpose of an assignment operator is to copy all the data from the source object into the current(target) object making sure, if necessary, that buffers are allocated as required if the class uses pointers to allocated data rather than only uses data types (which you class doesn't I believe).

commented: Rep for this monster thread +3

Thanks, I'll be reading

Thanks a lot Banfa, it's been solved.

John

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.