0

Let us suppose I want to model propositional formulae.

A formula is either a proposition, the negation of a formula, the conjunction of two formulae or the disjunction of two formulae.
Additional, formulae are associated with a truth value (i.e. true or false).

Ideally, I would want to model it like that:

class Formula { // abstract class
  protected:
    bool value;
  public:
    ~Formula() = 0;
};

class Proposition : public Formula {
  private:
    string name;
  public:
    Proposition(string s, bool b) : value(b), name(s) {}
};

class Negation : public Formula {
  private:
    Formula* f;
  public:
    Negation(Formula* nested) : value(!nested->value), f(nested) {}
};

class Conjunction : public Formula {
  private:
    Formula* l;
    Formula* r;
  public:
    Conjunction(Formula* f1, Formula* f2) : value(f1->value && f2->value), l(f1), r(f2) {}
};

// Disjunction similar to Conjunction

However, I cannot access the value attribute of nested, f1 and f2 (see https://stackoverflow.com/a/12271018/3923424 e.g.)

To overcome that, I added a public function get_value(), but I do not find it very elegant.
I also want to avoid making value public, as other classes should not be able to modify this attribute.
Finally, I could make all the derived classes friends of Formula. But I am not entirely convinced that this is the best and/or simplest solution.

Is there an elegant way to solve this problem?

Bonus question: what if I want value to be only accessible by the derived classes?

Community
  • 1
  • 1
R2B2
  • 1,541
  • 1
  • 12
  • 19
  • 1
    Why 'get_value()' is not elegant? It's almost standard way to create getter to field, that should be accessed for read in other classes. – ForEveR May 16 '17 at 10:19
  • 1
    instead of initalizing the base class members you should call an appropriate base class constructor. Btw I think the answer you linked isnt really relavent, because it is about a case where a protected member is supposed to be accesed in a class that does not inherit, which isnt the case here – 463035818_is_not_an_ai May 16 '17 at 10:23
  • @ForEveR: After reading http://stackoverflow.com/a/4684309/3923424 and http://stackoverflow.com/a/1568230/3923424, using a getter is probably not too bad in the end. But it would not work if I want `value` to be only accessible by the derived classes. – R2B2 May 16 '17 at 10:28
  • @tobi303: Good answer, thanks. But in my actual code, `Formula` is an abstract class... I will update the question accordingly. – R2B2 May 16 '17 at 10:30
  • 1
    I mean, you might be able to pull this off with some tricks, like a protected method that is friend to the base class and thus can be only used from children of base and access a member of a base object it gets as a parameter. Of course, this is ugly, and you totally shouldn't do it. The usual way would be some method in the base class that does what you want and bears all the responsibility. A getter would probably do. Or some method that refines something you give it. – Aziuth May 16 '17 at 10:33
  • 1
    If Formula is an abstract class, then how can the derived classes have objects of Formula as a member? You'd need something like pointers if they are supposed to be able to bear derived class objects. – Aziuth May 16 '17 at 10:35
  • @Aziuth: Yes, I need pointers instead of plain objects... Thanks. – R2B2 May 16 '17 at 10:41

2 Answers2

0

You can use a protected static getter in Formula to achieve this:

class Formula {
protected:
    bool value;

    static bool getValue(Formula& f) {
        return f.value;
    }

    Formula(bool value) : value(value) {}

public:
    virtual ~Formula() = 0;
};

then...

class Conjunction : public Formula {
private:
    Formula* l;
    Formula* r;

public:
    Conjunction(Formula* f1, Formula* f2) :
        Formula(Formula::getValue(*f1) && Formula::getValue(*f2)),
        l(f1), r(f2) {}
};

Here is a working full example.

user31601
  • 2,482
  • 1
  • 12
  • 22
0

If you want the data member to be protected in order to prevent it being changed, you can still make the constant value publicly visible. This can be in form of a ordinary const getter (either static or not), or in form of a type conversion operator to const bool, i.e.

class Formula {
protected:
  bool value;
public:
  /* ... */
  operator bool() const { return value; }
};
Walter
  • 44,150
  • 20
  • 113
  • 196