member access

V

Valeriu Catina

Hi,

consider the Shape class from the FAQ:

class Shape{

public:
Shape();
virtual ~Shape();
virtual void draw() = 0;
};


Now we have several derived shapes:

class Rectangle : public Shape{

public:
Rectangle();

void draw();

private:
double a; // width
double b; // height
};


class Circle{

public:
Circle();
void draw();

private:
double r; // radius
};

// more derived shapes follow

For each shape I would need to access its member variables. For this one
can add member functions in each derived class, for instance,
something like this in the Rectangle class:

double get_width() const
{
return a;
}

For a Shape derived class which would have many member variables, I
find it rather annoying and not very elegant to implement one get/set
member function for each member variable.

Is there any other way to gain access to the derived classes data,
(except making its member variables public)


Greetings,

Vali
 
H

Hari

Valeriu Catina je napisao:
Hi,

consider the Shape class from the FAQ:

class Shape{

public:
Shape();
virtual ~Shape();
virtual void draw() = 0;
};


Now we have several derived shapes:

class Rectangle : public Shape{

public:
Rectangle();

void draw();

private:
double a; // width
double b; // height
};


class Circle{

public:
Circle();
void draw();

private:
double r; // radius
};

// more derived shapes follow

For each shape I would need to access its member variables. For this one
can add member functions in each derived class, for instance,
something like this in the Rectangle class:

double get_width() const
{
return a;
}

For a Shape derived class which would have many member variables, I
find it rather annoying and not very elegant to implement one get/set
member function for each member variable.

Is there any other way to gain access to the derived classes data,
(except making its member variables public)


Greetings,

Vali

You can break traditional OOP and make some member variables public.
Note that this can break OOP very badly, my style is to allow access
of member variables ONLY if changing this member variable will not
change internal class state - eg. in your class Circle, changing 'r'
will not change internal state, but if you have member function
get_area() that saves area of circle, than every change to 'r' from
outside will break class state :

class Circle{

public:
Circle();
void draw();
double get_area() { return area; }
void set_radius(double nr) { r = nr; area = r * r * pi; }
private:
double r;
double area;
};

In upper class, changing r with set_radius will change internal state
(area) and if user can access r directly, than this state will be bad.
You can change get_area like:

double get_area() { return r * r * pi; }

to allow direct access to 'r'. Note that this will cost some
additional computation, most time user will set radius once, and call
get_area when needed.

For small classes this can be easily done, but for some large, it is
not easy to see if direct change to member variable will change state
of class.

Note: this is my way of programming, and probably it is wrong way :)

Best,
Zaharije Pasalic
 
S

Salt_Peter

Hi,

consider the Shape class from the FAQ:

class Shape{

public:
Shape();
virtual ~Shape();
virtual void draw() = 0;

};

Now we have several derived shapes:

class Rectangle : public Shape{

public:
Rectangle();

void draw();

private:
double a; // width
double b; // height

};

class Circle{

public:
Circle();
void draw();

private:
double r; // radius

};

// more derived shapes follow

For each shape I would need to access its member variables. For this one
can add member functions in each derived class, for instance,
something like this in the Rectangle class:

double get_width() const
{
return a;
}

For a Shape derived class which would have many member variables, I
find it rather annoying and not very elegant to implement one get/set
member function for each member variable.

Is there any other way to gain access to the derived classes data,
(except making its member variables public)

Greetings,

Vali


For what purpose? Give an example. You could provide pointers or
references but the question is why?
Consider a virtual member function that calculates area(). Its the
member function that requires access to the members. Each type
calculates area in its own special way. I don't need to access the
circle's radius or the rectangle's width and height to calculate
area().
Let a virtual member function area() do it for me.

class Shape{

public:
Shape();
virtual ~Shape();
virtual void draw() = 0;
double area() const = 0;

};

Nothing stops you from providing an accessor to the members, i just
don't see why this shoud be a requirement.
 
B

bjeremy

Valeriu said:
Hi,

consider the Shape class from the FAQ:

class Shape{

public:
Shape();
virtual ~Shape();
virtual void draw() = 0;
};


Now we have several derived shapes:

class Rectangle : public Shape{

public:
Rectangle();

void draw();

private:
double a; // width
double b; // height
};


class Circle{

public:
Circle();
void draw();

private:
double r; // radius
};

// more derived shapes follow

For each shape I would need to access its member variables. For this one
can add member functions in each derived class, for instance,
something like this in the Rectangle class:

double get_width() const
{
return a;
}

For a Shape derived class which would have many member variables, I
find it rather annoying and not very elegant to implement one get/set
member function for each member variable.

Is there any other way to gain access to the derived classes data,
(except making its member variables public)


Greetings,

Vali

Writing accessors is pretty standard. With accessors at least you can
control access to your data... but more importantly, if you find
yourself giving away the internals of your class this usually
signifies maybe a design problem.
 
H

Howard

Valeriu Catina said:
Hi,

consider the Shape class from the FAQ:

class Shape{

public:
Shape();
virtual ~Shape();
virtual void draw() = 0;
};


Now we have several derived shapes:

class Rectangle : public Shape{

public:
Rectangle();

void draw();

private:
double a; // width
double b; // height
};


class Circle{

public:
Circle();
void draw();

private:
double r; // radius
};

// more derived shapes follow

For each shape I would need to access its member variables.

Why? What do you plan to *do* with the derived class objects? So far, all
I see is a common draw() function. What would the code that accesses these
objects need that internal information for?

-Howard
 
S

Salt_Peter

Valeriu Catina je napisao:


















You can break traditional OOP and make some member variables public.
Note that this can break OOP very badly, my style is to allow access
of member variables ONLY if changing this member variable will not
change internal class state - eg. in your class Circle, changing 'r'
will not change internal state, but if you have member function
get_area() that saves area of circle, than every change to 'r' from
outside will break class state :

class Circle{

public:
Circle();
void draw();
double get_area() { return area; }
void set_radius(double nr) { r = nr; area = r * r * pi; }
private:
double r;
double area;

};

In upper class, changing r with set_radius will change internal state
(area) and if user can access r directly, than this state will be bad.
You can change get_area like:

double get_area() { return r * r * pi; }

to allow direct access to 'r'. Note that this will cost some
additional computation, most time user will set radius once, and call
get_area when needed.

For small classes this can be easily done, but for some large, it is
not easy to see if direct change to member variable will change state
of class.

Note: this is my way of programming, and probably it is wrong way :)

Best,
Zaharije Pasalic

You don't need to store the area as a member, since that might change
anyways should the cricle's metrics/size be modified. And you don't
require a setter since you already have one - the ctor(s).

class Shape {
public:
Shape() { }
virtual ~Shape() = 0;
virtual double area() const = 0;
};

Shape::~Shape() { }

class Circle : public Shape {
double m_r;
public:
Circle(double r = 0.0)
: m_r(r) { }
double area() const { return m_r * m_r * 3.1416; }
};

class Rectangle : public Shape {
double m_w;
double m_h;
public:
Rectangle(double w = 0.0, double h = 0.0)
: m_w(w), m_h(h) { }
double area() const { return m_w * m_h; }
};

int main()
{
Circle circle(10);
std::cout << "circle's area = ";
std::cout << circle.area() << std::endl;
Rectangle rect(10, 10);
std::cout << "rect's area = ";
std::cout << rect.area() << std::endl;
}
 
J

James Kanze

Valeriu Catina wrote:

[...]
Writing accessors is pretty standard.

Actually, it's not. There are definitly exceptions, but most of
the time, a lot of accessors is indicative of a poorly designed
hierarchy.
With accessors at least you can
control access to your data... but more importantly, if you find
yourself giving away the internals of your class this usually
signifies maybe a design problem.

Exactly. In his case, what is the semantics of "width()"? What
does it mean to ask the width of an object? Maybe he should
have a virtual function in the base class (which might do more
than just return a member variable in some derived
classes---what is the width of a rotated rectangle?)). Or maybe
it makes no sense at all to have the function anywhere.
 
H

Hari

Salt_Peter je napisao:
You don't need to store the area as a member, since that might change
anyways should the cricle's metrics/size be modified. And you don't
require a setter since you already have one - the ctor(s).

class Shape {
public:
Shape() { }
virtual ~Shape() = 0;
virtual double area() const = 0;
};

Shape::~Shape() { }

class Circle : public Shape {
double m_r;
public:
Circle(double r = 0.0)
: m_r(r) { }
double area() const { return m_r * m_r * 3.1416; }
};

class Rectangle : public Shape {
double m_w;
double m_h;
public:
Rectangle(double w = 0.0, double h = 0.0)
: m_w(w), m_h(h) { }
double area() const { return m_w * m_h; }
};

int main()
{
Circle circle(10);
std::cout << "circle's area = ";
std::cout << circle.area() << std::endl;
Rectangle rect(10, 10);
std::cout << "rect's area = ";
std::cout << rect.area() << std::endl;
}

As I say, my way is probably wrong way.
You don't need to store the area as a member, since that might change
anyways should the cricle's metrics/size be modified. And you don't
require a setter since you already have one - the ctor(s).

In class Circle, calculating area is easy (and with no overhead - 3
multiplications) but in some complex
classes, I wanna to precalculate some data based on some member
variable (even more likely, based on more variables). In some cases
using ctor/copy can be time consuming or if we talk about shapes, why
do we need to limit user to change radius of Circle?

I repeat, this is my way (and probably wrong way). This topic is to
far from original, question, so...


Best,
Zaharije Pasalic
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top