St4rb0y
St4rb0y

Reputation: 309

Can class object attributes call methods that return a value that the attribute should have in C++?

Why can't I simply call a class object attribute (i.e. sum) that calls a calls method (i.e. calculateSum()) that returns the value that attribute should have? What am I overlooking here? I know about how getter and setter functions are usually used, but I like the shortcut of simply calling an attribute that gets then itself updated with a method?

Entity.h:

class Entity {
public:
  Entity(int x, int y);
  ~Entity();

  int x, y;
  int sum = calculateSum();

private:
  int calculateSum();
};

Entity.cpp:

#include "Entity.h"

Entity::Entity(int x, int y) {
  this->x = x;
  this->y = y;
}

Entity::~Entity() {

}

int Entity::calculateSum() {
  return x + y;
}

main.cpp:

#include <iostream>
#include "Entity.h"

int main() {
  entity = Entity(5, 7);
  std::cout << entity.sum << std::endl; // outputs 0, should be 12!!
}

Is this even possible? Or are there any alternatives?

Thanks. :)

Upvotes: 4

Views: 1803

Answers (3)

Alex
Alex

Reputation: 94

Check std::function and lambda expressions. But in general, you have to use () to invoke a function, like:

std::cout << entity.sum() << std::endl; // outputs 0, should be 12!!

Upvotes: 1

songyuanyao
songyuanyao

Reputation: 172934

In your code, the initialization order for class Entity is:

  1. x is default-initialized to indeterminate value
  2. y is default-initialized to indeterminate value
  3. sum is initialized as calculateSum()
  4. the body of the constructor is performed (x and y are assigned to the function parameters).

As you can see, when data member sum is initialized from calculateSum(), in which the data member x and y are used but they're just default-initialized, still not get assigned as you expected in the constructor body.

You can initialize them in member initializer list.

Entity::Entity(int x, int y) : x(x), y(y) {
}

Then the order would be (same as the above in concept, but effect changes):

  1. x is direct-initialized to the constructor parameter x
  2. y is direct-initialized to the constructor parameter y
  3. sum is initialized as calculateSum()
  4. the body of the constructor is performed (does nothing)

LIVE

Upvotes: 3

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122585

C++ has no "attributes" like other languages do. The way to achieve what you want is to make sum a function:

class Entity {
public:
  Entity(int x, int y);
  ~Entity();

  int x, y;
  int sum() { return calculateSum(); }

private:
  int calculateSum();
};

As this is C++, there is of course a way to get something more close to what you want. That would require you to make sum an instance of a type that has an conversion operator to int that calls the calculateSum method to retrieve the value, though I don't think it is worth go there when you can simply make sum a method.

PS: As pointed out in another answer, you can get the expected output for your example, but you cannot (easily) get the correct sum after assigning a different value to x or y after construction.

Upvotes: 3

Related Questions