473,545 Members | 2,043 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Design problem - proxy class acting as a reference to object

Hello!

I have a matrix class like this:

class MyObject;

// MyMatrix is contains MyObjects
class MyMatrix {
public:
...
MyObject& operator() (int coll, int row);
...
private:
}

Now, this allows me writing code like this:

MyMatrix mat;
MyObject obj1, obj2;

mat (2,3) = obj1;
obj2 = mat (3,2);

So far, so good.
MyMatrix also keeps some private constants that hold coordinates of some
special MyObjects, so retrieving of those special MyObjects is faster. For
example:

struct coordinates {
int col, row;
}

class MyMatrix {
public:
...
MyObject& operator() (int coll, int row);
...
private:
coordinates specialMyObject ;
}

Because of operator(), client of MyMatrix is allowed to freely edit
contents of MyMatrix object, thus invalidating specialMyObject .
Now, I could write publicly available method Refresh () that refreshes
state of internal constants. There are two ways how this methods could be
used:

1.) Client must call it after editing MyMatrix object.
2.) It is called internally, by each method that relies on internal
constants, before those methods start their work.

Number 2.) is definitely bad because keeping state of object so it doesn't
have to be checked thoroughly each time needed, and then check it
thoroughly each time it is needed, completely nullifies purpose of internal
constants.

Number 1.) works fine, but from the OO view looks bad, because object
should take care of its internal data, not the client of that object. So,
there is something wrong with:

MyObject& MyMatrix::opera tor() (int coll, int row);

I could either replace it with

MyObject MyMatrix::opera tor() (int coll, int row);

and add method:

void MyMatrix::Asign Object (int coll, int row, const MyObject& obj);

but this invalidates expression:

mat (2,3) = obj1;

Or I could write some kind of proxy class that acts as a reference to
MyObject but also changes state of MyMatrix object when needed.

What would that proxy class look like? I don't know where to start from, so
links or google search keywords would be greatly appreciated.
Jul 23 '05 #1
8 3519
On Sun, 24 Apr 2005 21:43:51 -0700, Kanenas wrote:
[...]
Play around with the above and see if it works for you.

[...]

Kanenas


After some adjustments for my real code, your code works perfectly. Thank
you very much, it is exactly what I needed...
Jul 23 '05 #2
Just out of curiosity, I tried the following:

/** matrix.h **/
#ifndef MATRIX_H__
#define MATRIX_H__

class MyMatrix
{
private:
class MyMatrixElement
{
private:
MyMatrix& watched;
MyObject& el;
size_t col, row;

public:
MyMatrixElement (MyMatrix& matr, MyObject& obj,
size_t c, size_t r)
: watched(matr), el(obj), col(c), row(r) {}

template <typename _Type>
MyMatrixElement & operator=(_Type from)
{ el = from; watched.refresh (col, row); return *this;}

//operator MyObject() { return el; }
operator const MyObject&() const { return el; }
};

MyObject _object;

void refresh(size_t, size_t) {}

public:
const MyObject& operator()(size _t col, size_t row) const;
MyMatrixElement operator()(size _t col, size_t row);
};

#endif /*MATRIX_H__*/

/** matrix.cpp **/
class MyObject
{
public:
MyObject & add(int) { return *this; }
};

//typedef int MyObject;

#if defined __GNUC__
typedef unsigned long size_t;
#endif

#include "matrix.h"

const MyObject& MyMatrix::opera tor()(size_t, size_t) const
{
return _object;
}

MyMatrix::MyMat rixElement MyMatrix::opera tor()(size_t col, size_t row)
{
return MyMatrixElement (*this, _object, col, row);
}

int main(void)
{
MyMatrix matrix;
MyObject obj;

obj = matrix(0, 0); /* weird behaviour */
matrix(1, 1) = obj;
matrix(3, 3) = MyObject(matrix (2, 2)).add(1);

return 0;
}
As you can see I removed "operator MyObject() { return el; }" since
Visual studio wouldn't compile with both that one and "operator const
MyObject&() const { return el; }".
And I don't realy see the use in both of them anyway, but that could be
caused by my inexpierience.

Now the main thing I'm wondering is at the line I commented with weird
behaviour, I noticed that with Visual Studio as well as gcc the method
"MyMatrix::MyMa trixElement MyMatrix::opera tor()(size_t col, size_t row)"
is called followed by "MyMatrixElemen t::operator const MyObject&()
const". In my opinion it would be far easier and faster to just call
"const MyObject& MyMatrix::opera tor()(size_t col, size_t row) const".

Can anyone explain this behaviour?

Thanks,
Mark
Jul 23 '05 #3
SpOiLeR wrote:
Hello!

I have a matrix class like this:

class MyObject;

// MyMatrix is contains MyObjects
class MyMatrix {
public:
...
MyObject& operator() (int coll, int row);
...
private:
}

Now, this allows me writing code like this:

MyMatrix mat;
MyObject obj1, obj2;

mat (2,3) = obj1;
obj2 = mat (3,2);

So far, so good.
MyMatrix also keeps some private constants that hold coordinates of some special MyObjects, so retrieving of those special MyObjects is faster. For example:

struct coordinates {
int col, row;
}

class MyMatrix {
public:
...
MyObject& operator() (int coll, int row);
...
private:
coordinates specialMyObject ;
}

Because of operator(), client of MyMatrix is allowed to freely edit
contents of MyMatrix object, thus invalidating specialMyObject .
Now, I could write publicly available method Refresh () that refreshes state of internal constants. There are two ways how this methods could be used:

1.) Client must call it after editing MyMatrix object.
2.) It is called internally, by each method that relies on internal
constants, before those methods start their work.

Number 2.) is definitely bad because keeping state of object so it doesn't have to be checked thoroughly each time needed, and then check it
thoroughly each time it is needed, completely nullifies purpose of internal constants.

Number 1.) works fine, but from the OO view looks bad, because object
should take care of its internal data, not the client of that object. So, there is something wrong with:

MyObject& MyMatrix::opera tor() (int coll, int row);

I could either replace it with

MyObject MyMatrix::opera tor() (int coll, int row);

and add method:

void MyMatrix::Asign Object (int coll, int row, const MyObject& obj);
but this invalidates expression:

mat (2,3) = obj1;

Or I could write some kind of proxy class that acts as a reference to
MyObject but also changes state of MyMatrix object when needed.

What would that proxy class look like? I don't know where to start from, so links or google search keywords would be greatly appreciated.


I still don't completely understand why you would need the proxy class,
and what the proxy class would do for you in this requirement, however
consider the following method for a matrix class, that allows the use
of syntax similar to C-Style [][] double index brackets.
See following link:
http://code.axter.com/dynamic_2d_array.h
You can use it like this:
int SizeX = 3;
int SizeY = 5;
dynamic_2d_arra y<MyObject> mat(SizeX, SizeY);
MyObject obj1, obj2;
mat[2][3] = obj1;
obj2 = mat[2][3];

This type of syntax is more natural for C/C++ environment, and
therefore IMHO, easier to read.

See following link for a few more different versions of above
dynamic_2d_arra y class, including one version that uses std::vector,
and allows for resize.
http://www.tek-tips.com/faqs.cfm?fid=5575

Jul 23 '05 #4
On 25 Apr 2005 07:49:26 -0700, Axter wrote:
SpOiLeR wrote:
[...]
I still don't completely understand why you would need the proxy class,


Then re-read original post... I want to update MyObject's internals without
client needing to interfere in that.
of syntax similar to C-Style [][] double index brackets.
FAQ has something about this, and why it should better to be avoided, and
replaced with operator()...
See following link:
http://code.axter.com/dynamic_2d_array.h
You can use it like this:
int SizeX = 3;
int SizeY = 5;
dynamic_2d_arra y<MyObject> mat(SizeX, SizeY);
MyObject obj1, obj2;
mat[2][3] = obj1;
obj2 = mat[2][3];

This type of syntax is more natural for C/C++ environment, and
therefore IMHO, easier to read.


Thanks, but that's not what I wanted, anyway check Kanennas post above to
see what I mean.
Jul 23 '05 #5
On Mon, 25 Apr 2005 16:09:53 +0200, Capstar wrote:
Just out of curiosity, I tried the following:

/** matrix.h **/
#ifndef MATRIX_H__
#define MATRIX_H__

class MyMatrix
{
private:
class MyMatrixElement
{
private:
MyMatrix& watched;
MyObject& el;
size_t col, row;

public:
MyMatrixElement (MyMatrix& matr, MyObject& obj,
size_t c, size_t r)
: watched(matr), el(obj), col(c), row(r) {}

template <typename _Type>
MyMatrixElement & operator=(_Type from)
{ el = from; watched.refresh (col, row); return *this;}

//operator MyObject() { return el; }
operator const MyObject&() const { return el; }
};

MyObject _object;

void refresh(size_t, size_t) {}

public:
const MyObject& operator()(size _t col, size_t row) const;
MyMatrixElement operator()(size _t col, size_t row);
};

#endif /*MATRIX_H__*/

/** matrix.cpp **/
class MyObject
{
public:
MyObject & add(int) { return *this; }
};

//typedef int MyObject;

#if defined __GNUC__
typedef unsigned long size_t;
#endif

#include "matrix.h"

const MyObject& MyMatrix::opera tor()(size_t, size_t) const
{
return _object;
}

MyMatrix::MyMat rixElement MyMatrix::opera tor()(size_t col, size_t row)
{
return MyMatrixElement (*this, _object, col, row);
}

int main(void)
{
MyMatrix matrix;
MyObject obj;

obj = matrix(0, 0); /* weird behaviour */
matrix(1, 1) = obj;
matrix(3, 3) = MyObject(matrix (2, 2)).add(1);

return 0;
}
As you can see I removed "operator MyObject() { return el; }" since
Visual studio wouldn't compile with both that one and "operator const
MyObject&() const { return el; }".
gcc works fine, don't have MSVC, so can't try it. But IMHO it should work!
And I don't realy see the use in both of them anyway, but that could be
caused by my inexpierience. Now the main thing I'm wondering is at the line I commented with weird
behaviour, I noticed that with Visual Studio as well as gcc the method
"MyMatrix::MyMa trixElement MyMatrix::opera tor()(size_t col, size_t row)"
is called followed by "MyMatrixElemen t::operator const MyObject&()
const". In my opinion it would be far easier and faster to just call
"const MyObject& MyMatrix::opera tor()(size_t col, size_t row) const".

Can anyone explain this behaviour?

Thanks,
Mark


If you have const MyMatrix object, you won't be able to call constructor
for MyMatrixElement because it takes non-const reference to MyMatrix. So,
for const MyMatrix you will need to have

const MyObject& MyMatrix::opera tor()(size_t col, size_t row) const

as a reference operator, because const object would'n be able to call

MyMatrixElement operator()(size _t col, size_t row);

So, you need both.

If you have non const MyMatrix object, and ask for non const Myobject&:

MyMatrix mat;
Myobject& objref = mat (2,3);

you will get compile time error because there MyMatrixElement can't be
converted into non const Myobject&. This is exactly what was wanted,
because we don't want client to reference directly MyObject
unless it just reads them (either by obtaining copy, or const&).

That's why you need both:

operator MyObject() { return el; }
operator const MyObject&() const { return el; }

So, to conclude, you can either get copy or const reference, but if you
want to change anything on MyObject you will have to do it through
reference operator, i.e.

matrix (2,3) = obj; // This would refresh our matrix
Jul 23 '05 #6
Capstar wrote:
Just out of curiosity, I tried the following:

/** matrix.h **/
#ifndef MATRIX_H__
#define MATRIX_H__
Don't do this. Any identifier with two consecutive underscores is
reserved to the implementation. Use MATRIX_H_ instead.
[redacted]

Jul 23 '05 #7
SpOiLeR wrote:
On 25 Apr 2005 07:49:26 -0700, Axter wrote:
SpOiLeR wrote:
[...]
I still don't completely understand why you would need the proxy

class,
Then re-read original post... I want to update MyObject's internals without client needing to interfere in that.
of syntax similar to C-Style [][] double index brackets.
FAQ has something about this, and why it should better to be avoided,

and replaced with operator()...


I've read the FAQ, and the information on the FAQ is base on a method
that returns a temporary Type to allow access to second [] index.
My class does not use that method, and therefore the class I posted is
much more efficient.
It's as efficient, if not more efficient then using operator().
Moreover, it's more compatible to C-Style syntax, and therefore easier
to use and read.
It's much better to use common syntax methods, then to use methods that
result in having to use ambiguous syntax.

Jul 23 '05 #8
On Mon, 25 Apr 2005 16:09:53 +0200, Capstar <ne**@ge.homeip .net>
wrote:
Just out of curiosity, I tried the following:
[...]
int main(void)
{
MyMatrix matrix;
MyObject obj;

obj = matrix(0, 0); /* weird behaviour */
matrix(1, 1) = obj;
matrix(3, 3) = MyObject(matrix (2, 2)).add(1);

return 0;
}
As you can see I removed "operator MyObject() { return el; }" since
Visual studio wouldn't compile with both that one and "operator const
MyObject&() const { return el; }".
And I don't realy see the use in both of them anyway, but that could be
caused by my inexpierience.
I put that in mostly out of habit. Normally when there's a conversion
operator returning a reference, there will be a corresponding
conversion operator differing only in its const-ness and the
const-ness of the returned reference.

Offhand, I can't think of a situation using 'MyMatrixElemen t::operator
MyObject()' that can't be handled with 'MyMatrixElemen t::operator
const MyObject&()' and possibly a temporary created via MyObject's
copy constructor.
Now the main thing I'm wondering is at the line I commented with weird
behaviour, I noticed that with Visual Studio as well as gcc the method
"MyMatrix::MyM atrixElement MyMatrix::opera tor()(size_t col, size_t row)"
is called followed by "MyMatrixElemen t::operator const MyObject&()
const". In my opinion it would be far easier and faster to just call
"const MyObject& MyMatrix::opera tor()(size_t col, size_t row) const".

Can anyone explain this behaviour?

Here are three reasons for you to consider:

1) matrix is non-const, so matrix(0,0) binds to the non-const
'MyMatrix::oper ator()(size_t, size_t)'. Const-overloading resolution
is modeled thusly: non-static methods are given an "implicit object
parameter". E.g. for 'X::f(...)' the implicit object parameter is
'X&' and for 'X::f(...) const' it's 'const X&'. Consider:
X x;
x.f(/* ... */);
From the view of the resolver, binding 'x.f' to 'X::f(...) const'
requires an implicit conversion of 'x' to a 'const X&' while binding
'x.f' to 'X::f(...)' requires no conversions. 'X::f(...)' is thus the
best viable function.

2) Picking the const version over the non-const as being the "better"
would require examining the context of the call to
'MyMatrix::oper ator()'. This is outside the realm of C++ semantic
context sensitivity.

3) (a biggie) An optimizer could examine context and pick the const
version, but this may produce undesirably different behavior (which
includes return type, return value, exceptions and side effects) than
calling the non-const operator(). There's no semantic or (except for
some operators) connotative connection between const-overloaded
methods at the language level; though they may often be semantically
similar when implemented, that's only a matter of convention. Even
with operator[], the const version can be semantically different from
the non-const version.
As an example, consider map from the STL.
'map<...>::oper ator[](const Key& k)' creates an entry if none exists
for 'k'. There's no 'map<...>::oper ator[](const Key& k) const', but
it's easy to imagine an extended library which defined one. The const
[] shouldn't create an entry; instead, it could throw an out_of_range
exception. Suppose compilers were allowed to call the const indexing
operator when its result is used as an rvalue and consider the
following fragment:
map<std::string , int> settings;
//...
try {
//if "debug_leve l" isn't set, it defaults to 0
dbg_lvl = settings["debug_leve l"];
} catch (std::out_of_ra nge) {dbg_lvl=0;}
For safety's sake, you have to catch a possible out_of_range
exception. If the compiler ends up binding 'foo[name]' to
'map<...>::oper ator[](std::string)', no out_of_range is ever thrown
but you still incur the overhead of the try/catch block. Note also
that all the try/catch does is produce the behavior of the non-const
[]. IMO, blech.

If you want to ensure 'MyMatrix::oper ator() const' is called, you can
use a cast to make 'matrix' const.

Kanenas
Jul 23 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
1447
by: nitrogenycs | last post by:
Hello, I need a way to get a notification whenever a variable of an object changes. The approach should be non-intrusive so that I can use existing objects without modifying them. I want to be notified no matter who or what did change the wrapped object - even whenever an object internal methods changes the variables. So I coded the piece...
5
2205
by: Carl Bevil | last post by:
I'm creating a library for internal use that relies on third-party code. I don't want clients of this library to know anything about the third party code, when compiling or running. Generally I've been achieving this by having an abstract base class which defines an interface, and inheriting a concrete class which defines the...
10
1314
by: John Wood | last post by:
I have a class (B) that derives from another class (A) - it provides a specialization of that base class. It turns out that the base class (A) needs to be replaceable. That is, I need to be able to plug in new implementations (retaining the same interface). I cannot change the source code of A or B, it needs to be in a library that is...
3
1945
by: Marty McDonald | last post by:
Using Visual Studio.Net... I have two classes, one derives from the other. My web service accepts the base class as input, it returns the derived class as the return value. When I set a web reference to that web service, the web service proxy is incorrect! It creates its own version of the base class fine, but when it creates its own...
0
4818
by: Paul Hastings | last post by:
Hi All - I am trying to build a Web Service that can be accessed using an Excel spreadsheet. I have been able to do this for relatively simple access to the Web Service. But now I need to add authentication using a client certificate and that is where I am stuck.
6
2862
by: sameer | last post by:
..NET Framework 1.1 VS2003 Application is making webservice calls from behind a proxy server and then freezes and dies. Questoin is can i use webservice over proxy server( i guess another name of them is ISA ... if i a not wrong), if yes how? Sameer
0
5096
by: Richard Gregory | last post by:
Hi, I have the wsdl below, for an Axis web service, and when I select Add Web Refernce in Visual Studio the proxy is missing a class representing the returnedElementsType (see reference.cs below the wsdl). This complex type is a collection of another complex type(elementType), and the Reference.cs has an array of these rather than the...
4
1998
by: Fabio | last post by:
An ASP.NET 2.0 web site contains a web form and a web service. The web form consumes the web service. There is a Book class in the App_Code folder. The web service exposes a method that returns a Book object. The consumer includes a method that require a Book parameter. However the Book generated proxy class conflicts with the Book class in...
2
1379
by: gartnerjmoody | last post by:
I have a web service that has a method that takes a created .NET class like this: method(my.Shared.BO.InfoClass info, bool isItem) The actual web service gets this class from an assembly, Shared.BO.dll I have a Windows Workflow that needs to call this, and the Workflow itself is being passed an object of this type...
0
7468
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7401
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7656
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7808
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7423
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
3450
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3443
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1884
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1014
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.