Creating a member of a class that is automatically calculated from other members of the class?

  • I am an absolute beginner when it comes to programming, and I'm trying to teach myself the basics by simply solving some simple “problems” in C ++.

  • I searched the Internet for the exact answer to my question before posting it here, and have not yet found it, however this may be due to (1).

So, I'm looking for a way to declare a member of a class that is automatically computed from other members of the same class, so that the computed member of the class can be used in the same way as an explicitly defined member of the class. For example, imagine a structure called a creature that has properties / members creature.numberofhands, creature.fingersperhand, and finally a creature.totalfingers property that is automatically calculated from the above members.

Here is an example of the closest I was aiming for:

#include <iostream>

typedef struct creature {
    int numberofhands;
    int fingersperhand;
    int totalfingers();
} creature;    

int creature::totalfingers()
{
    return numberofhands * fingersperhand;
};

int main()
{
    creature human;
    human.numberofhands = 2;
    human.fingersperhand = 5;

    printf("%d",human.totalfingers());
    return(0);
}

What really annoys me is that I have to consider a computed one DIFFERENT from clearly defined ones, i.e. I need to put "()" after it. How can I change the code, so I can use: human.totalfingers without ever defining it explicitly?

+4
5

- . - :

class Creature {
public:
    Creature(int numhands, int fingersperhand) // constructor
        : m_numhands{numhands}, m_fingersperhand{fingersperhand}
        { }
    int fingersPerHand() const { return m_fingersperhand; }
    int numberOfHands() const { return m_numhands; }
    int totalFingers() const { return numberOfHands() * fingersPerHand(); }

private:
    const int m_numhands;
    const int m_fingersperhand;
};

- . - , , , .

:

#include <iostream>
int main()
{
    Creature human{2, 5};
    std::cout << "A human has "
        << human.totalFingers() << " fingers. "
        << human.fingersPerHand() << " on each of their "
        << human.numberOfHands() << " hands.\n";
    return 0;
}

- - ( , ), :

class CreatureV2 {
public:
    int fingersPerHand() const { return m_fingersperhand; }
    int numberOfHands() const { return m_numhands; }
    int totalFingers() const { return numberOfHands() * fingersPerHand(); }

    void setFingersPerHand(int num) { m_fingersperhand = num; }
    void setNumberOfHands(int num) { m_numhands = num; }

private:
    // Note: these are no longer `const` and I've given them default
    // values matching a human, so if you do nothing you'll get
    // human hands.
    int m_numhands = 2;
    int m_fingersperhand = 5;
};

:

#include <iostream>
int main()
{
    CreatureV2 human;
    std::cout << "A human has "
        << human.totalFingers() << " fingers. "
        << human.fingersPerHand() << " on each of their "
        << human.numberOfHands() << " hands.\n";

    CreatureV2 monster;
    monster.setFingersPerHand(7);
    monster.setNumberOfHands(5);
    std::cout << "A monster has "
        << monster.totalFingers() << " fingers. "
        << monster.fingersPerHand() << " on each of their "
        << monster.numberOfHands() << " hands.\n";

    CreatureV2 freak;
    freak.setFingersPerHand(9);
    // Note: I forgot to specify the number of hands, so a freak get 
    // the default 2.
    std::cout << "A freak has "
        << freak.totalFingers() << " fingers. "
        << freak.fingersPerHand() << " on each of their "
        << freak.numberOfHands() << " hands.\n";

    return 0;
}

: , ++ 14.

+5

, , , "- " - ++.

, , - .

, # D, "", , ++ .

+2

, - ( ):

class RefMul
{
public:
    RefMul(int& a, int& b) : a(a), b(b) {}

    operator int() const { return a * b; }

private:
    int& a;
    int& b;
};

struct creature {
    int numberofhands;
    int fingersperhand;
    RefMul totalfingers{numberofhands, fingersperhand};
};

. RefMul printf, int:

printf("%d", int(human.totalfingers));

, ++:

std::cout << human.totalfingers;
+2

, . - , -. , , , - -, .

+1

. , , - - ( @Jesper Juhl).

, , , . ( # Groovy) ++, ++. SO ++. - Microsoft Visual ++ (, Microsoft Visual ++). Visual ++ MSDN. Visual ++, :

struct creature {
    int numberofhands; // use of public member variables are generally discouraged
    int fingersperhand;

    __declspec(property(get = get_totalfingers)) // Microsoft-specific
    int totalfingers;

private:
    int fingers;
    int get_totalfingers() 
    {
        return numberofhands * fingersperhand; // This is where the automatic calculation takes place. 
    }
}; 

:

#include <iostream>
int main()
{
    creature martian;
    martian.numberofhands = 2;
    martian.fingersperhand = 4; // Marvin the Martian had 4!

    // This line will print 8
    std::cout << "Total fingers: " << martian.totalfingers << std::endl;

    return 0;
}

As I said before, properties are not a standard C ++ function, but there are ways to get them in C ++ that either rely on smart tricks or use compiler-specific functions. IMHO, using simple functions (as described by @Jesper Juhl), is a better alternative.

0
source

Source: https://habr.com/ru/post/1681725/


All Articles