Hi,
I would like to use covariant return types in mutual dependent classes like:
class IB;
class IA {
virtual IB* getIB() = 0;
};
class IB{
virtual IA* getIA() = 0;
};
class B;
class A : public IA{
B *getIB(); /// Here I get an error!
// If I replace with IB * getIB(); everything works fine
};
class B : public IB {
A* getIA();
};
I understand, that the compiler cannot know - at the time of the
declaration of A::getIB() - that B derives from IB. Is there a way to do
some sort of forward declaration with "inheritance information" in order
to get the example to work?
thanks in advance
Martin 8 2641
"Martin Stettner" <no****@martin.dot.stettner.at.complement.dot.at > wrote in
message news:ct*********@newsreader1.utanet.at... Hi,
I would like to use covariant return types in mutual dependent classes
like: class IB; class IA { virtual IB* getIB() = 0; }; class IB{ virtual IA* getIA() = 0; };
class B; class A : public IA{ B *getIB(); /// Here I get an error! // If I replace with IB * getIB(); everything works fine };
class B : public IB { A* getIA(); };
I understand, that the compiler cannot know - at the time of the declaration of A::getIB() - that B derives from IB.
That is not the problem. The problem is that you're trying
to override a virtual function, but your return value is not
the same as that of the function you're trying to override.
This is not allowed. All of: the name, arguments, and return
type must be identical.
Is there a way to do some sort of forward declaration with "inheritance information" in order to get the example to work?
What specifically are you trying to do?
-Mike
"Mike Wahler" <mk******@mkwahler.net> wrote in message
news:GZ****************@newsread3.news.pas.earthli nk.net... "Martin Stettner" <no****@martin.dot.stettner.at.complement.dot.at > wrote in message news:ct*********@newsreader1.utanet.at... Hi,
I would like to use covariant return types in mutual dependent classes like: class IB; class IA { virtual IB* getIB() = 0; }; class IB{ virtual IA* getIA() = 0; };
class B; class A : public IA{ B *getIB(); /// Here I get an error! // If I replace with IB * getIB(); everything works fine };
class B : public IB { A* getIA(); };
I understand, that the compiler cannot know - at the time of the declaration of A::getIB() - that B derives from IB.
That is not the problem. The problem is that you're trying to override a virtual function, but your return value is not the same as that of the function you're trying to override. This is not allowed. All of: the name, arguments, and return type must be identical.
No, they need not all be identical. Specifically, the
return type can vary, as long as, for an override in
a derived class, the return type has a base that is
the return type in the base class. That is what the
phrase 'covariant return types' means. For example,
this is legal C++:
class BR {};
class DR : public BR {};
class B {
public: virtual BR & covaret();
};
class D : public B {
public: virtual DR & covaret();
};
--
--Larry Brasfield
email: do***********************@hotmail.com
Above views may belong only to me.
Mike Wahler wrote: "Martin Stettner" <no****@martin.dot.stettner.at.complement.dot.at > wrote in message news:ct*********@newsreader1.utanet.at...
... class IB; class IA { virtual IB* getIB() = 0; }; class IB{ virtual IA* getIA() = 0; };
class B; class A : public IA{ B *getIB(); /// Here I get an error! // If I replace with IB * getIB(); everything works fine };
class B : public IB { A* getIA(); };
That is not the problem. The problem is that you're trying to override a virtual function, but your return value is not ...
There's already an answer to this in the thread: The return type of a
derived function can be derived from the return type of the base function...
... What specifically are you trying to do?
I'm trying to separate interface and implementation (I heard that's a
good thing :-) ...)
IA and IB in the above code represent some interface classes to a
module. A and B implement these interfaces. From outside the module, a
client only knows that getIA returns an IA (and getIB and IB).
But inside the module, it would be nice to indicate that the methods
actually return the respective subclasses (if not, I'd either have to
implement a second method pair getA/getB or to do some nasty casting...)
Perhaps there's someone who can tell me how to solve the problem (or at
least tell me, that there's certainly no solution...) -Mike
--
Martin
Martin Stettner wrote: Mike Wahler wrote:class IB; class IA { virtual IB* getIB() = 0; }; class IB{ virtual IA* getIA() = 0; };
class B; class A : public IA{ B *getIB(); /// Here I get an error! // If I replace with IB * getIB(); everything works fine };
class B : public IB { A* getIA(); };
That's tricky :).
The standard says that the covariant return type shall be complete at
the point of declaration of the method in the derived class (or it can
be the derived class type) I'm trying to separate interface and implementation (I heard that's a
good thing :-) ...)
I heard that too :). But now I'm learning c# :( Perhaps there's someone who can tell me how to solve the problem (or
at least tell me, that there's certainly no solution...)
Try this:
|struct IA
|{
| struct IB
| {
| virtual IA* getIA();
| };
| virtual IB* getIB();
|};
|typedef IA::IB IB;
|struct A : public IA
|{
| struct B : public IB
| {
| virtual A* getIA();
| };
| virtual B* getIB();
|};
|typedef A::B B;
Comeau c++ online say it's ok. VC 7.1 doesn't like it :).
....
Best regards,
Bogdan Sintoma
"Martin Stettner" <no****@martin.dot.stettner.at.complement.dot.at >
wrote in message news:ct**********@newsreader1.utanet.at... Mike Wahler wrote: "Martin Stettner" <no****@martin.dot.stettner.at.complement.dot.at > wrote in message news:ct*********@newsreader1.utanet.at...
... class IB; class IA { virtual IB* getIB() = 0; }; class IB{ virtual IA* getIA() = 0; };
class B; class A : public IA{ B *getIB(); /// Here I get an error! // If I replace with IB * getIB(); everything works fine };
class B : public IB { A* getIA(); };
That is not the problem. The problem is that you're trying to override a virtual function, but your return value is not ... There's already an answer to this in the thread: The return type of a derived function can be derived from the return type of the base function...
... What specifically are you trying to do?
I'm trying to separate interface and implementation (I heard that's a good thing :-) ...)
Often it is, but not as a matter of dogma.
IA and IB in the above code represent some interface classes to a module. A and B implement these interfaces. From outside the module, a client only knows that getIA returns an IA (and getIB and IB).
It seems to me that having the interface methods
return implementation classes rather than simply
the interface is confounding the boundary between
interface and implementation. Is there a particular
reason you need to blur that distinction?
But inside the module, it would be nice to indicate that the methods actually return the respective subclasses (if not, I'd either have to implement a second method pair getA/getB or to do some nasty casting...)
You are free, inside the module, and within the
implementation class, to add methods and friends
as necessary to get the functionality you need
internally. The second method pair need not be
expensive. In fact, the interface implementation
can use that pair to do the real work.
Perhaps there's someone who can tell me how to solve the problem (or at least tell me, that there's certainly no solution...)
I am not expert enough to claim no solution exists, but I
could not think of any way to do exactly what you asked.
The problem is that the inheritance relationship cannot be
described independently of the class definition, so there
is an inherent circularity (as you have found) where each
subclass, to be defined as you desire, must have the other
class already defined. Without breaking the subclasses
into two, (separating out some more interface), there is
no way to break that circular dependency.
The answer, IMHO, is to get interface and implementation
considerations more cleanly separated, first in your own
thinking then in the code.
--
--Larry Brasfield
email: do***********************@hotmail.com
Above views may belong only to me.
Larry Brasfield wrote: "Martin Stettner" <no****@martin.dot.stettner.at.complement.dot.at > wrote in message news:ct**********@newsreader1.utanet.at...
Mike Wahler wrote:
"Martin Stettner" <no****@martin.dot.stettner.at.complement.dot.at > wrote in message news:ct*********@newsreader1.utanet.at...
... class IB; class IA { virtual IB* getIB() = 0; }; class IB{ virtual IA* getIA() = 0; };
class B; class A : public IA{ B *getIB(); /// Here I get an error! // If I replace with IB * getIB(); everything works fine };
class B : public IB { A* getIA(); };
[some snip] Often it is, but not as a matter of dogma.
I agree with you on that point... IA and IB in the above code represent some interface classes to a module. A and B implement these interfaces. From outside the module, a client only knows that getIA returns an IA (and getIB and IB).
It seems to me that having the interface methods return implementation classes rather than simply the interface is confounding the boundary between interface and implementation. Is there a particular reason you need to blur that distinction?
I think I understand your arguments, but I'm not sure if I agree with
them: The interface is clearly defined using IA and IB (whose methods
also just return interface pointers). So no class using the interfaces
will have any clue about the implementation.
On the other hand, it's also well defined (in my case), that A and B
implement the methods in a way, that they always return objects of type
B and A respectively. And every part that works with the two
implementation classes knows about this.
So I would like to express this fact in code, and I think, that's one of
the reasons, covariant return types were introduced (but I may be wrong
on this last point). [...] internally. The second method pair need not be expensive. In fact, the interface implementation can use that pair to do the real work.
Actually, it wouldn't be expensive at all: The implementation just
returns an internal member pointer. But writing two methods which do
exactly the same thing the same way bothers me.
[...] The problem is that the inheritance relationship cannot be described independently of the class definition, so there
That's what I wasn't sure about: It could have been that there were some
syntax to do this kind of forward declaration for inheritances. But if
this is impossible, of course I have to find some other way.
... The answer, IMHO, is to get interface and implementation considerations more cleanly separated, first in your own thinking then in the code.
I think, the way I want to do this is not so wrong. But this possibly
leads us to some sort of dogmatic discussion we both want do avoid here,
don't we?
But thank you very much for your thoughts, they push me to rethink my
design (which isn't a bad thing too, as i heard ...)
Martin
P.S: Sorry to the newsgroup purists: This subthread evolves away from a
language-specific topic, so I'll stop it here...
Bogdan Sintoma wrote: Martin Stettner wrote:
[...[
That's tricky :).
Isn't it? :-)
The standard says that the covariant return type shall be complete at the point of declaration of the method in the derived class (or it can be the derived class type)
Would be nice to drop that restriction and instead allow to declare
incomplete types with inheritance relations... (what speaks against this
idea? But that's just a thought of mine, not a serious proposal, please
don't blame me for it...)
... Try this: |struct IA |{ | struct IB | { | virtual IA* getIA(); | }; | virtual IB* getIB(); |}; |typedef IA::IB IB; |struct A : public IA |{ | struct B : public IB | { | virtual A* getIA(); | }; | virtual B* getIB(); |}; |typedef A::B B;
Wow, I wouldn't have come up with this! But sadly there's no good reason
why my IB should be a member of IA (if I'd use this, it'd have to mean
something...) Comeau c++ online say it's ok.
Interesting: At the point of the declaration of B::getIA, A is not a
complete type, and getIA() is not a member of A (but of A::B). So,
conforms this to the standard?
VC 7.1 doesn't like it :).
Bad news, as this is the compiler I have to use for this project.
... Best regards, Bogdan Sintoma
Thanks a lot
Martin
Martin Stettner wrote: Bogdan Sintoma wrote: Martin Stettner wrote: The standard says that the covariant return type shall be complete
at the point of declaration of the method in the derived class (or it
can be the derived class type) Would be nice to drop that restriction and instead allow to declare incomplete types with inheritance relations... (what speaks against
this idea? But that's just a thought of mine, not a serious proposal,
please don't blame me for it...)
I think you should search (and maybe post this question) on
comp.std.c++. ... Try this: |struct IA |{ | struct IB | { | virtual IA* getIA(); | }; | virtual IB* getIB(); |}; |typedef IA::IB IB; |struct A : public IA |{ | struct B : public IB | { | virtual A* getIA(); | }; | virtual B* getIB(); |}; |typedef A::B B; Wow, I wouldn't have come up with this!
:)
I cannot take credit for this. I've saw that code a while ago on
c++.moderated. Comeau c++ online say it's ok.
Interesting: At the point of the declaration of B::getIA, A is not a complete type, and getIA() is not a member of A (but of A::B). So, conforms this to the standard?
I'm not sure.
The main problem here is that you cannot forward declare the
inheritance relationship. Since, in this example the type of A is well
known (at compile time) at the point of declaration of getIA, I think
it should be ok.
..
..
Bogdan This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Alex Vinokur |
last post by:
Hello,
Here is some program with virtual constructors.
Is there any difference between
* clone1() vs. clone2()
* create1() vs. create2() ?
It seems that it should be.
|
by: Sankar Nemani |
last post by:
Hi,
Does anyone know what the reason behind not allowing to
use "covariant return types when overriding methods in
derived classes" in C# is?
Also while other OO languages such as Java, don't...
|
by: Stefan Slapeta |
last post by:
Hi,
this code does not compile in C#:
class base_class {}
class derived_class : base_class {}
class A
{
public virtual base_class f()
|
by: Stephen Walch |
last post by:
Error C2392 is hitting me hard!
I have a managed C++ library that implements a bunch of fixed interfaces.
For example, one interface is:
public abstract interface IDbCommand
{
public...
|
by: Mike |
last post by:
I keep running into the scenario below over and over again. Currently I get
around not having covariant return types by using an interface and explicit
property definitions which works to some...
| |
by: Bob Hairgrove |
last post by:
Consider the classic clone() function:
class A {
public:
virtual ~A() {}
virtual A* clone() const = 0;
};
class B : public A {
public:
|
by: miked |
last post by:
Why are there still no covariant return types?
All searches reveal no workarounds accept for using an interface which is a
real pain. I wind up missing this capability almost every time I...
|
by: Alex Vinokur |
last post by:
Here is a code from
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8
--------------------------------------
class Shape {
public:
virtual ~Shape() { } // A...
|
by: kikazaru |
last post by:
Is it possible to return covariant types for virtual methods inherited
from a base class using virtual inheritance?
I've constructed an example below, which has the following structure:
Shape...
|
by: Rahul |
last post by:
Hi Everyone,
I was trying to implement covariant return types and i get a
compilation error,
class BB : public AA
{
};
class A
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
| |
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |