Topic: Const base classes.


Author: "Bradd W. Szonye" <bradds@concentric.net>
Date: 1998/01/19
Raw View
Oleg Zabluda wrote in message <69esu7$1bu@marianna.psu.edu>...
>
>Well, I didn't have a specific problem in mind when I wrote
>the original posts. It was more like pondering. I was thinking
>like this: inheritance is a form of composition. We allow
>const members. Therefore const base subobjects must be allowed
>aa well so the the need for a subobject to be const did not
>affect the decision whether to make it a member or a base
>class.

First, inheritance is not a form of composition; it is implemented in terms
of composition in C++. Inheritance and composition model two different types
of relationships; it simply happens that composition is often an appropriate
implementation of inheritance, because subclasses will almost always
represent their inherited data in the same way as the superclass. However,
this is not always true: a balanced binary tree is-a binary tree, but it may
require a substantially different data representation.

I think the need for a subobject to be const does influence the decision: it
implies that the relationship should be 'has-a' rather than 'is-a'. A class
with a "const base class" would likely violate the Liskov Substitution
Principle badly, and therefore be badly designed. This is similar to the way
that assignment semantics in C++ usually cause classes derived from concrete
base classes to violate the LSP: a circle is-an ellipse, but a circle
variable is not an ellipse because the assignment semantics violate the LSP.

You could argue that a "foo: public const bar" is-a const bar, but what does
that really mean in modeling terms? Although...

Perhaps const derivation is a way to deal with the assignment LSP problem: a
circle variable is-a const ellipse variable, that is, a circle value is-an
ellipse value, but they are incompatible as variables.

What do others think? Do "const" bases aggravate or alleviate the LSP
problem? Keep in mind the additional problems with multiple inheritance
ambiguity; the circle-ellipse application might be a real use, or it might
just be an ugly hack.
---
Bradd W. Szonye
bradds@concentric.net
http://www.concentric.net/~Bradds
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: rich_paul@bigfoot.com (Rich Paul)
Date: 1998/01/21
Raw View
In article <69ueqv$4ga@examiner.concentric.net>, bradds@concentric.net
says...

>>Perhaps const derivation is a way to deal with the assignment LSP
>>problem: a circle variable is-a const ellipse variable, that is, a
>>circle value is-an ellipse value, but they are incompatible as
>>variables.

My suggestion on that is to read Scott Meyers on deriving from
concrete classes ... wouldn't it be better to do this:

class TCompleteCurve {
 private:
 TCompleteCurve &operator = ( const TCompleteCurve & );
};
class TElipse : public TCompleteCurve {
 public:
 TElipse &operator = ( const TElipse & );
 TElipse &operator = ( const TCircle & );
};
class TCircle : public TCompleteCurve {
 public:
 TCircle &operator = ( const TElipse & );
};

Of course, it doesn't allow one to assign from a generic
CompleteCurve, but should it?  Also, it allows an assignment from
Circle to Ellipse, but not from Ellipsee to Circle ... but there's
a problem there, as well ... Now you've got an Ellipse, before you
had a circle.  Just ask the vtable!

So going ever further:
class TCompleteCurve {
 public:
 class TCompleteCurveImpl {
  TCompleteCurveImpl *clone()const;
 };
 TCompleteCurveImpl *Impl;
};
class TEllipseImpl : public TCompleteCurveImpl {
 TEllipseImpl *clone()const;
};
class TCircleImpl : public TCompleteCurveImpl {
 TCircleImpl *clone()const;
};

This is a thought ... a TCompleteCurve is ALWAYS a TCompleteCurve.
Your choice whether a TCompleteCurve that contains an Ellipse
should change it's Impl to be a Circle when the width and height are
equal.  Perhaps a bool isCircle() member, which always returns true
in TCircle and checks in TEllipse would be preferable.

Perhaps a TPolygon would be a good idea, rather than TSquare and
TRectangle.  With a TRegularPolygonImpl and a TPolygonImpl.  Perhaps
a template Impl:
template<unsigned I>
class TPolygonImpl {
 const static int Sides = I;
 TPoint Vertices[I];
};
template<unsigned I>
class TRegularPolygonImpl {
 const static int Sides = 1;
 int   SideLength;
};

This is kind of pretty, but I've never used it in a program, so I
don't know if it would work in practice ... in theory, there is
no difference between theory in practice, but in practice there
generally is.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Oleg Zabluda <zabluda@math.psu.edu>
Date: 1998/01/14
Raw View
Steve Clamage <stephen.clamage_nospam@Eng.Sun.COM> wrote:
: On 03 Jan 98 09:37:13 GMT, Oleg Zabluda <zabluda@math.psu.edu> wrote:

: >1. Is the following legal?
: >
: >class A{};
: >class B : const A {};
: >
: >My reading of the C++ grammar in CD2 is that it's not.

: It is not. The grammar does not allow cv-qualifiers in the
: base-specifier.

[...]

: The base-specifier must be a class name (see 10 "Derived classes"). A
: typedef name is a class name if it names a class (see 9.1 "Class
: names"). In this case, CA does not (just) name a class, but represents
: a type with cv-qualifiers*. I agree the draft could be more clear on
: this point, and perhaps this could become the subject of a
: clarification.

: As to why cv-qualifiers are not allowed on base classes, I suppose it
: is because no one thought it would be useful. I don't remember the
: question ever coming up before. You could make the symmetry argument
: that if cv-qualified members are allowed, cv-qualified bases should
: also be allowed. But I don't see that as a very strong argument.

Well, I do. I guess I am just one of those "orthogonal" nuts.

: Maybe
: you have an example of a common programming problem that can't be
: solved conveniently without such a feature.

Well, I didn't have a specific problem in mind when I wrote
the original posts. It was more like pondering. I was thinking
like this: inheritance is a form of composition. We allow
const members. Therefore const base subobjects must be allowed
aa well so the the need for a subobject to be const did not
affect the decision whether to make it a member or a base
class. As for concrete examples why one might want to use
that, here is one:

using std::string;

class named {
  private:
    string s_;
  public:
    named(const string& s) : s_(s) {}
    const string& name() const { return s_; }
    named& rename(const string& s) { s_ = s; return *this; }
    virtual ~named() {}
};

class file : public named {
// some things can be renamed.
};

class city : public const named {
// some don't [1]
};

[1] Incidently, this also removes the default copy assignement
operator, just like a const member would. I am not aware
of any case when somebody needed to destroy a perfectly good
city and buid an absolute copy of some other one instead :-)


As for why nobody needs it, I guess because nobody though of
it, or at least don't admit it in public. For example, many
classes in stdlib should have used const inheritance, had
it beed available. For example (24.3.3):

struct input_iterator_tag {};
struct forward_iterator_tag : public const input_iterator_tag {};

Oleg.
--
Life is a sexually transmitted, 100% lethal disease.


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/01/09
Raw View
Steve Clamage wrote:
>
> On 03 Jan 98 09:37:13 GMT, Oleg Zabluda <zabluda@math.psu.edu> wrote:
>
> >1. Is the following legal?
> >
> >class A{};
> >class B : const A {};
> >
> >My reading of the C++ grammar in CD2 is that it's not.
>
> It is not. The grammar does not allow cv-qualifiers in the
> base-specifier.
>
> >2. Is the following legal?
> >
> >class A{};
> >typedef const A CA;
> >class B : const CA {};
> >
> >My reading of the C++ grammar in CD2 is that it is.
>
> I think you meant to write
>         class B : CA {}; // without the 'const'
>
> The grammar is not the whole story, since some restrictions are
> expressed in semantic rules. In this case, however, the grammar
> implicitly disallows the code.
>
> The base-specifier must be a class name (see 10 "Derived classes"). A
> typedef name is a class name if it names a class (see 9.1 "Class
> names"). In this case, CA does not (just) name a class, but represents
> a type with cv-qualifiers*. I agree the draft could be more clear on
> this point, and perhaps this could become the subject of a
> clarification.
>
> As to why cv-qualifiers are not allowed on base classes, I suppose it
> is because no one thought it would be useful. I don't remember the
> question ever coming up before. You could make the symmetry argument
> that if cv-qualified members are allowed, cv-qualified bases should
> also be allowed. But I don't see that as a very strong argument. Maybe
> you have an example of a common programming problem that can't be
> solved conveniently without such a feature.

I think there would also be some questions to be answered if const bases
were to be allowed, f. ex.:

class A
{
public:
  void f();
  void g();
  void g() const;
};

class B: public virtual A {};

class C: public virtual const A {};

class D: public B, public C {};

void foo()
{
  D d;
  d.f(); // legal? (D::B::A is not const, D::C::A is const,
         //         but both are the same object!)
  d.g(); // is A::g() or A::g() const called, or is this call ambiguous?
}
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Oleg Zabluda <zabluda@math.psu.edu>
Date: 1998/01/03
Raw View
1. Is the following legal?

class A{};
class B : const A {};

My reading of the C++ grammar in CD2 is that it's not.
Question: why not?

2. Is the following legal?

class A{};
typedef const A CA;
class B : const CA {};

My reading of the C++ grammar in CD2 is that it is.

Just checking.

P.S. Egcs-1.0 and Sun's CC 4.2 accept it, but both get it wrong. The
     type of B::CA is A, not ``const A''.


The ``const'' dude.
--
Life is a sexually transmitted, 100% lethal disease.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: stephen.clamage_nospam@Eng.Sun.COM (Steve Clamage)
Date: 1998/01/05
Raw View
On 03 Jan 98 09:37:13 GMT, Oleg Zabluda <zabluda@math.psu.edu> wrote:

>1. Is the following legal?
>
>class A{};
>class B : const A {};
>
>My reading of the C++ grammar in CD2 is that it's not.

It is not. The grammar does not allow cv-qualifiers in the
base-specifier.

>2. Is the following legal?
>
>class A{};
>typedef const A CA;
>class B : const CA {};
>
>My reading of the C++ grammar in CD2 is that it is.

I think you meant to write
 class B : CA {}; // without the 'const'

The grammar is not the whole story, since some restrictions are
expressed in semantic rules. In this case, however, the grammar
implicitly disallows the code.

The base-specifier must be a class name (see 10 "Derived classes"). A
typedef name is a class name if it names a class (see 9.1 "Class
names"). In this case, CA does not (just) name a class, but represents
a type with cv-qualifiers*. I agree the draft could be more clear on
this point, and perhaps this could become the subject of a
clarification.

As to why cv-qualifiers are not allowed on base classes, I suppose it
is because no one thought it would be useful. I don't remember the
question ever coming up before. You could make the symmetry argument
that if cv-qualified members are allowed, cv-qualified bases should
also be allowed. But I don't see that as a very strong argument. Maybe
you have an example of a common programming problem that can't be
solved conveniently without such a feature.

 ---
 * "cv-qualifier" means "const", "volatile", or "const volatile".

---
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]