Topic: Q: Member access control and pure virtual methods (legal code or compiler bug?)
Author: Hyman Rosen <hymie@prolifics.com>
Date: 1998/08/01 Raw View
Brent McPherson wrote:
> class I {
> public:
> virtual int AddRef() = 0;
> virtual int interface_method() = 0;
> };
>
> class B {
> public:
> int ref;
> virtual int AddRef() {return ref++;}
> };
>
> class C : public B, public I {
> B::AddRef; // This resolves the ambiguity in the call to AddRef below
> int interface_method() { AddRef(); return 0; }
> };
>
> void factory ()
> {
> C* l_pC = new C;
> }
You need to check out section 10.3 of the standard, about final overriders.
To get the effect you want, do the following:
struct I { virtual int AddRef() = 0; virtual int interface_method() = 0; };
struct B : virtual I { int ref; int AddRef() { return ref++; } };
struct C : B { int interface_method() { AddRef(); return 0; } };
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/08/01 Raw View
Brent McPherson wrote:
>
> Hi,
>
> I have a question regarding the standard and whether the code below is
> legal? The motivation for this is to avoid having to override pure virtual
> methods defined in a COM interface. (which results in an extra layer of
> indirection) In other words, I want to avoid overriding C::AddRef which
> would simply call B::AddRef.
>
> This seems to be a gray area so any help in interpreting what the C++
> standard says about this code would be helpful. Note: The following code
> works if the methods in class "I" are not declared as pure virtual. (but
> because this is a COM interface I cannot change class "I")
>
> Compiling this program generates the following error:
> error C2259: 'C' : cannot instantiate abstract class due to following
> members:
> warning C4259: 'int I::AddRef(void)' : pure virtual function was not
> defined
>
> So, who is right, the compiler or my code?
>
> class I {
> public:
> virtual int AddRef() = 0;
> virtual int interface_method() = 0;
> };
>
> class B {
> public:
> int ref;
> virtual int AddRef() {return ref++;}
> };
>
> class C : public B, public I {
> B::AddRef; // This resolves the ambiguity in the call to AddRef below
> int interface_method() { AddRef(); return 0; }
> };
>
> void factory ()
> {
> C* l_pC = new C;
> }
The correct way to do is:
class B: public virtual I
{
int ref;
public:
virtual int AddReg() { return ref++; }
};
class C: public virtual I, public B
{
// no ambiguity with AddRef here!
int interface_method() { AddRef(); return 0; }
};
This of course assumes that you can modify B. I can remain unchanged.
If you cannot change B either (say, it's in a library), I don't
see a way to avoid the redirection.
Maybe there should be a feature for that (since the implementation
would be easy - just point the vtbl slot of that function to the B
implementation -, but cannot be provided by the programmer - since
the vtbl is inaccessible). (In the next version of the standard, of
course)
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Brent McPherson" <nospam@nospam.com>
Date: 1998/07/30 Raw View
Hi,
I have a question regarding the standard and whether the code below is
legal? The motivation for this is to avoid having to override pure virtual
methods defined in a COM interface. (which results in an extra layer of
indirection) In other words, I want to avoid overriding C::AddRef which
would simply call B::AddRef.
This seems to be a gray area so any help in interpreting what the C++
standard says about this code would be helpful. Note: The following code
works if the methods in class "I" are not declared as pure virtual. (but
because this is a COM interface I cannot change class "I")
Compiling this program generates the following error:
error C2259: 'C' : cannot instantiate abstract class due to following
members:
warning C4259: 'int I::AddRef(void)' : pure virtual function was not
defined
So, who is right, the compiler or my code?
class I {
public:
virtual int AddRef() = 0;
virtual int interface_method() = 0;
};
class B {
public:
int ref;
virtual int AddRef() {return ref++;}
};
class C : public B, public I {
B::AddRef; // This resolves the ambiguity in the call to AddRef below
int interface_method() { AddRef(); return 0; }
};
void factory ()
{
C* l_pC = new C;
}
Thanks!
--
Brent McPherson (brent_mcpherson @ softimage . co . uk)
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: davidp@lanovatoin.com (David A. Pickett)
Date: 1998/07/30 Raw View
Since you're inheriting from I, you *must* override the pure virtual
function I::AddRef (). The situation would be different if B also
derived from I. So, the compiler is right.
On 30 Jul 98 13:56:54 GMT, "Brent McPherson" <nospam@nospam.com>
wrote:
>Hi,
>
>I have a question regarding the standard and whether the code below is
>legal? The motivation for this is to avoid having to override pure virtual
>methods defined in a COM interface. (which results in an extra layer of
>indirection) In other words, I want to avoid overriding C::AddRef which
>would simply call B::AddRef.
>
[...]
>
>class I {
>public:
> virtual int AddRef() = 0;
> virtual int interface_method() = 0;
>};
>
>class B {
>public:
> int ref;
> virtual int AddRef() {return ref++;}
>};
>
>class C : public B, public I {
> B::AddRef; // This resolves the ambiguity in the call to AddRef below
> int interface_method() { AddRef(); return 0; }
>};
>
>void factory ()
>{
> C* l_pC = new C;
>}
>
>Thanks!
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Kannan Chellappan <chellapk@nmasd.bel.alcatel.be>
Date: 1998/07/30 Raw View
Brent McPherson wrote:
> Hi,
>
> I have a question regarding the standard and whether the code below is
> legal? The motivation for this is to avoid having to override pure virtual
> methods defined in a COM interface. (which results in an extra layer of
> indirection) In other words, I want to avoid overriding C::AddRef which
> would simply call B::AddRef.
>
> This seems to be a gray area so any help in interpreting what the C++
> standard says about this code would be helpful. Note: The following code
> works if the methods in class "I" are not declared as pure virtual. (but
> because this is a COM interface I cannot change class "I")
To my knowledge, what you are doing is not legal. If you derive from a
abstract class, then all the pure virtual functions have to be defined before
you instantiate an object. This means that class I has two member functions
which are pure virtual (and hence have to be defined to instantiate). In the
class C, you have defined one of the member functions. The other (AddRef) is
still pure virtual. By deriving from B (which also has a member function by
name AddRef), you are NOT overriding, the virtual function AddRef in the
class I. As far as the compiler is concerned, AddRef is a function in both
class B and class I and they are different.
eg,
class A {
public:
int fn();
};
class B {
public:
int fn();
};
class C : public A, public B {
public:
int fn()
{
A::fn();
B::fn(); // these calls are legal. The one defined in B, does not override
the one defined in A.
}
Hope this answers your question.
If you derive the class B from class I, and class C from B alone, then you
can instantiate the object of class C without defining the function AddRef in
class C.
But be informed that if you do as above, class B will become a abstract
class. (You can instantiate an object of type B, if you simply define the
body of AddRef in B with { } ).
wishes
>
>
>
> class I {
> public:
> virtual int AddRef() = 0;
> virtual int interface_method() = 0;
> };
>
> class B {
> public:
> int ref;
> virtual int AddRef() {return ref++;}
> };
>
> class C : public B, public I {
> B::AddRef; // This resolves the ambiguity in the call to AddRef below
> int interface_method() { AddRef(); return 0; }
> };
>
> void factory ()
> {
> C* l_pC = new C;
> }
>
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]