>> 2. I made a simple little 3D viewer for some of my data (which was
>> impressively easy :) ). However, I use TPolyLine3D to do the
>> drawing and I can't get any of the lines to be drawn in different
>> colours. Currently I do something like:
<snip>
>
>Use TPolyLine3D::SetLinecolor(Color_t);
D'oh! - Read the manual!
Thanks ;)
Warning the next bit has turned out a bit long and academic!
>> As a general point tho, I think I am right in saying that multiple
>> inheritance of non-pure virtual classes (ie non-interfaces) in
>> object hierachies with a single shared parent base class (ie
>> TObject) cannot work ...that's why it isn't allowed in Java, .NET
>> etc
>
>It will work if you have _virtual_ inheritance! See also the ANSI/ISO
>C++ standard chapter 10. Suppose you have
>
> #include <iostream>
> #ifdef USE_VIRTUAL
> #define VIRTUAL virtual
> #else
> #define VIRTUAL
> #endif
>
> class A {
> public: virtual void f() { cout << "A:f" << endl; }};
>
> class B : VIRTUAL public A {
> #ifdef USE_OVERLOAD
> public: virtual void f() { cout << "B::f" << endl; }
> #endif
> };
>
> class C : VIRTUAL public A {
> #ifdef USE_OVERLOAD
> public: virtual void f() { cout << "C::f" << endl; }
> #endif
> };
>
> class D : public B, public C { };
>
> int main()
> {
> D d;
> d.f();
> return 0;
> }
>
>With USE_VIRTUAL undefined, it will not work, since you cannot find a
>unique calling sequence to A::f
>
> A A
> \ /
> B C
> \ /
> D
>
>Compiling with GCC like
>
> prompt% g++ foo.cxx -o foo
> foo.cxx: In function `int main()':
> foo.cxx:28: request for method `f' is ambiguous
>
>On the other hand, if we do define USE_VIRTUAL, it will work.
>
> prompt% g++ foo.cxx -o foo -DUSE_VIRTUAL
> prompt% ./foo
> A:f
>
>This is because we now have for A::f
>
> A
> / \
> B C
> \ /
> D
>
>Now, if we define USE_OVERLOAD, then we get into trouble again:
>
> prompt% g++ foo.cxx -o foo -DUSE_VIRTUAL -DUSE_OVERLOAD
> foo.cxx: In function `int main()':
> foo.cxx:27: cannot declare variable `d' to be of type `D'
> foo.cxx:27: since the following virtual functions need a final
> overrider: foo.cxx:27: void B::f()
> foo.cxx:28: request for method `f' is ambiguous
>
>So it seems C++ fares better than Java and .NET :-). Now, wether this
>would be a good strategy for ROOT classes to follow is an entirely
>different matter.
Hmm..interesting - I was unaware of this "feature". It is potentially quite
nice in that you can have interfaces with some implementation but you still
have to be explicit as you do with an interface (ie all interface functions
must be overloaded). The writer of class D then has to explicitly choose
which of the possible methods, B.F(), C.f(), A.f() if any to call in his
D.f(). Having thought about this for a few moments, there are 3 problems
that I can see with this:
1) Both B and C have access to the public/protected data members of A.
However, they are (programmatically) unaware of each other and have no
imposed duty to access those members in a consistent way (particularly the
protected ones). This could cause problems eg suppose the writer of D wants
to do something like:
f{
B.f();
C.f();
} (pseudo-code)
which would be a prefectly reasonable thing to do. But B.f() would leave a
variable in A in a different state from C.f(). The code for D.f() then
behaves very differently if it is instead
f{
C.f();
B.f();
}
which is not obviously different. Indeed, one of the 2 possibilities may
work, one may not - crashes etc are possible...its a potential minefield
2) Consider the case where neither B or C override f - there is no
problem
and D does not have to override f either. The writer of B then issues an
update in which he does override f - maybe to fix a bug or provide additional
functionality. He thinks that this is fine because he hasn't changed the
structure at all - he won't be breaking anyone's code. He is unaware of C.
The writer of D gets the update and thinks "great" and installs it thus
breaking his software.
3) In order for the writer of D to be able to override f()
satisfactorily
he will have to understand the details of the implementation of all of the
versions of f() that are above D in the hierachy thus placing on him the
burden of understanding someone else's code - assuming that code is even
available - if it is distibuted compiled with headers then he may not be able
to get access to the code at all.
Anyhow, that'll do for now - hope its understandable - it's probably a bit
hastily thought about in places!
But, well, thanks for pointing that out - in a closed enviroment it could be
useful. But I think in more open enviroments, then it probably shouldn't be
used! :)
Matt
This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:51:11 MET