Helper functions and data member access

Hi forum,

I want to override the << operator (Edit: override the '*' operator), and if I add,

friend const Hero& operator*(const Hero& first, const Hero& second);

into my Hero class, there is no issue when I am implementing. I can properly access the Hero data members.

But what if I dont want to make it a friend? How can I design it so that the function still has access to the data members?
Last edited on
and if I add,
It is not the operator<<

But what if I dont want to make it a friend?
Why not?

How can I design it so that the function still has access to the data members?
Depends on the members and what you try to accomplish. You can always have getters for the members.
This is for a school assignment, and in the specifications, it says,

1
2
3
4
5
Your design also includes a helper operator, which supports your class:

const SuperHero& operator*(const SuperHero& first, const SuperHe-ro& second): a non-friend 
that returns an unmodifiable reference to the winner of the battle between the SuperHeroes 
after max_rounds rounds.


Granting friendship pierces encapsulation, but without the friend keyword, I do not know how to access the data members. I could use a query, yes, but again -- I need to use this helper function as per specifications.

I've tried implementing it as,
1
2
3
4
5
6
7
8
9
10
11
	const SuperHero& SuperHero::operator*(const SuperHero& first, const SuperHero& second) {
		int counter = 0;
		SuperHero f(first.name, first.health, first.strength, first.supStrength, first.defStrength),
			s(second.name, second.health, second.strength, second.supStrength, second.defStrength);
		for (int i = 0; i < max_rounds; ++i) {
			while (f.Hero::isAlive() && s.Hero::isAlive()) {
				f.health = f.health - s.attackStrength() + f.defend();
				s.health = s.health - f.attackStrength() + s.defend();
				counter++;
			}
		}


But it's underlining operator* in red, saying there +1 overload. Also, data members of first and second are underlined in red (such as first.name and second.health), saying they are inaccessible.
Cheers

PS, I meant '*' instead of '<<', apologies.
Last edited on
const SuperHero& operator*(const SuperHero& first, const SuperHero& second): a non-friend...

It looks like a trap set up by your teacher :)
When defined outside classes, overloaded operators are usually declared friend to allow easy access to their private properties, but that’s not mandatory. As coder777 said:
coder777 wrote:
You can always have getters for the members.
In this case, it seems your teacher is pushing you to write getters/setters to access your private properties (or to declare them public).

So maybe you need something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class SuperHero {
private:
    std::string name;
    double health       {},
           strength     {},
           sup_strength {},
           def_strength {};
    // ...omissis...
public:
    std::string getName() const { return name; }
    void setName(const std::string& s) { name = s; }
    double getHealth() const { return health; }
    void setHealth(double d) { health = d; }
    // ...omissis...
};


To use in a way like this:
Edit: sorry, the following example is wrong, since you can't modify the objects passed by const reference. You definitely need to create a modifiable copy of them as you currently do in your code. Anyway, I hope I've been able to describe the general idea.
1
2
3
4
5
const SuperHero& SuperHero::operator*(const SuperHero& first, const SuperHero& second) {
    for (int i = 0; i < max_rounds; ++i) {
        while (first.isAlive() && second.isAlive()) {
            first.setHealth(first.getHealth() - second.attackStrength() + first.defend());
            // ... 


I’m a bit bemused by the request of having that overloaded operator returning a const reference, while it’s usually required to return by copy.
I’ve searched inside C++ Programming Language and en.cppreference.com and I couldn’t find any distinctive characteristic.
The C++ Programming Language, 4th Edition - 18.2.1 Binary and Unary Operators
Stroustrup wrote:
A binary operator can be defined by either a non-static member function taking one argument or a nonmember function taking two arguments.
...
A unary operator, whether prefix or postfix, can be defined by either a non-static member function taking no arguments or a nonmember function taking one argument.

Since operator* could be unary (indirection operator) or binary (multiplication operator), all these prototypes are legal:
http://en.cppreference.com/w/cpp/language/operator_member_access
http://en.cppreference.com/w/cpp/language/operator_arithmetic
1
2
3
4
5
6
7
8
9
 // unary - class members:
R & T::operator*();
R const & T::operator*() const;
// unary - outside class:
R& operator*(T a);
// binary - class member:
T T::operator*(const T2 &b) const;
// binary - outside class:
T operator*(const T &a, const T2 &b);

Last edited on
Registered users can post here. Sign in or register to post.