Covariant returns

  • Thread starter Thread starter Hasani
  • Start date Start date
H

Hasani

When implementing .net interfaces in vc++.net, is there anyway to get around
the "error C2392: : covariant returns types are not supported in managed
types" error?
I know how to do this in c#. Is it possible in c++.net 2003? If so, please
show me how? Will it be possible in c++.net 2005(beta?)?
 
Hasani,
When implementing .net interfaces in vc++.net, is there anyway to get around
the "error C2392: : covariant returns types are not supported in managed
types" error?
I know how to do this in c#. Is it possible in c++.net 2003?

Unfortunately, no, not directly. What C# does is not actually covariant
return types... it does a trick by which it "renames" the actual method
implementing the interface/base class method, and creates a new one with the
same name, essentialy.
If so, please
show me how? Will it be possible in c++.net 2005(beta?)?

With the new C++/CLI syntax, yes.
Consider this example:

#using <mscorlib.dll>
using namespace System;


public interface class IA
{
public:
Object^ GetIt();
};

public ref class B : public IA
{
protected:

virtual Object^ GetItFromIA() = IA::GetIt
{
return "Some other thing";
}

public:
virtual String^ GetIt() new
{
return "This is the String";
}
};


int main()
{
IA^ obj = gcnew B();
Console::WriteLine(obj->GetIt());
Console::WriteLine(((B^)obj)->GetIt());
}

Note: This is built using the May preview... haven't gotten beta 1 yet ;)
 
Tomas said:
Unfortunately, no, not directly. What C# does is not actually covariant
return types... it does a trick by which it "renames" the actual method
implementing the interface/base class method, and creates a new one with the
same name, essentialy.

could you please give me an example how to achive this in C#? I didn't
succeed :(

Stefan
 
c# example.

class MyObject : ICloneable
{

//by doing this, you're making the method private and in order to access
this method, the object must be (up)casted to the interface
//in question. In this case, an ICloneable.
//e.x.:
// MyObject obj = new MyObject();
//ICloneable clone = (ICloneable) obj;
//clone.Clone();
object ICloneable.Clone()
{
//do whatever u want. usually u call the Clone method that
returns a strong typed object as I'm doing now
return Clone();
}

public MyObject Clone()
{
return (MyObject) MemberwiseClone();
}
}
 
Well, this leads me to my next question.

How would u implement the following in c++

lets say in a c# I created

public interface IFoo
{
Int32 GetValue();
}

public interface IBar
{
String GetValue();
}

so here you have 2 interfaces with signatures that only differ by return
type. If I wanted to make a clas FooBar in c++ that implements/inherits both
interfaces, how would I go about doing this. Please provide a code example
as you did b4 but using synatax that will compile in c++.net 7.0/7.1 (no ^,
ref, etc).
 
Hasani said:
How would u implement the following in c++

[SNIP]

so here you have 2 interfaces with signatures that only differ by return
type. If I wanted to make a clas FooBar in c++ that implements/inherits
both interfaces, how would I go about doing this. Please provide a code
example as you did b4 but using synatax that will compile in c++.net
7.0/7.1 (no ^, ref, etc).

First, this is one place where the new syntax is superior to the old syntax.
You will have better reliability that the compiler can do the right thing in
the new syntax. I'll present both the old and new syntax for completeness.
Here is the new syntax:

using namespace System;

public interface class IFoo {
int GetValue();
};

public interface class IBar {
String^ GetValue();
};

public ref class R : IFoo, IBar {
public:
virtual int G1() = IFoo::GetValue;
virtual String^ G2() = IBar::GetValue;
};

int R::G1() { return 42; }
String^ R::G2() { return "Hello World!"; }

int main() {
R^ r = gcnew R;
IFoo^ f = r;
IBar^ b = r;

Console::WriteLine(f->GetValue());
Console::WriteLine(b->GetValue());
}

And here is the old syntax:

#using <mscorlib.dll>

using namespace System;

public __gc __interface IFoo {
int GetValue();
};

public __gc __interface IBar {
String* GetValue();
};

public __gc class R : public IFoo, public IBar {
public:
virtual int IFoo::GetValue();
virtual String* IBar::GetValue();
};

int R::IFoo::GetValue() { return 42; }
String* R::IBar::GetValue() { return S"Hello World!"; }

int main() {
R* r = new R;
IFoo* f = r;
IBar* b = r;

Console::WriteLine(f->GetValue());
Console::WriteLine(b->GetValue());
}
 
you've just added another subscriber to your blog!!

Thx Bray!

Brandon Bray said:
Hasani said:
How would u implement the following in c++

[SNIP]

so here you have 2 interfaces with signatures that only differ by return
type. If I wanted to make a clas FooBar in c++ that implements/inherits
both interfaces, how would I go about doing this. Please provide a code
example as you did b4 but using synatax that will compile in c++.net
7.0/7.1 (no ^, ref, etc).

First, this is one place where the new syntax is superior to the old syntax.
You will have better reliability that the compiler can do the right thing in
the new syntax. I'll present both the old and new syntax for completeness.
Here is the new syntax:

using namespace System;

public interface class IFoo {
int GetValue();
};

public interface class IBar {
String^ GetValue();
};

public ref class R : IFoo, IBar {
public:
virtual int G1() = IFoo::GetValue;
virtual String^ G2() = IBar::GetValue;
};

int R::G1() { return 42; }
String^ R::G2() { return "Hello World!"; }

int main() {
R^ r = gcnew R;
IFoo^ f = r;
IBar^ b = r;

Console::WriteLine(f->GetValue());
Console::WriteLine(b->GetValue());
}

And here is the old syntax:

#using <mscorlib.dll>

using namespace System;

public __gc __interface IFoo {
int GetValue();
};

public __gc __interface IBar {
String* GetValue();
};

public __gc class R : public IFoo, public IBar {
public:
virtual int IFoo::GetValue();
virtual String* IBar::GetValue();
};

int R::IFoo::GetValue() { return 42; }
String* R::IBar::GetValue() { return S"Hello World!"; }

int main() {
R* r = new R;
IFoo* f = r;
IBar* b = r;

Console::WriteLine(f->GetValue());
Console::WriteLine(b->GetValue());
}
 
Back
Top