真 OO无双
posts - 718, comments - 1240, trackbacks - 51, articles - 0
博客园
::
首页
::
新随笔
::
联系
::
订阅
::
管理
(原創) 一個C++能跑的泛型,但在C#卻不能跑<已解決> (C/C++) (template) (.NET) (C#) (C++/CLI)
Posted on 2007-06-16 14:16
真 OO无双
阅读(2508)
评论(27)
编辑
收藏
所属分类:
C/C++
、
C#
、
C++/CLI
、
.NET
、
template
ISO C++
1
/**/
/*
2
(C) OOMusou 2007
http://oomusou.cnblogs.com
3
4
Filename : Template_test1.cpp
5
Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
6
Description : template test
7
Release : 06/09/2007 1.0
8
*/
9
#include
<
iostream
>
10
11
using
namespace
std;
12
13
class
Interface1
{
14
public
:
15
virtual
void
func1()
=
0
;
16
}
;
17
18
class
Interface2
{
19
public
:
20
virtual
void
func1()
=
0
;
21
}
;
22
23
class
Class1 :
public
Interface1
{
24
public
:
25
void
func1()
{
26
cout
<<
"
Class1's func1
"
<<
endl;
27
}
28
}
;
29
30
class
Class2 :
public
Interface2
{
31
public
:
32
void
func1()
{
33
cout
<<
"
Class2's func1
"
<<
endl;
34
}
35
}
;
36
37
class
IGeneric
{
38
public
:
39
virtual
void
func1()
=
0
;
40
}
;
41
42
template
<
typename T
>
43
class
Generic1 :
public
IGeneric
{
44
private
:
45
T
*
_aClass;
46
47
public
:
48
Generic1(T
*
aClass)
{
49
_aClass
=
aClass;
50
}
51
52
void
func1()
{
53
_aClass
->
func1();
54
}
55
}
;
56
57
int
main()
{
58
Interface1
*
obj1
=
new
Class1;
59
Interface2
*
obj2
=
new
Class2;
60
61
IGeneric
*
foo
=
new
Generic1
<
Interface1
>
(obj1);
62
foo
->
func1();
63
64
foo
=
new
Generic1
<
Interface2
>
(obj2);
65
foo
->
func1();
66
67
delete obj1;
68
delete obj2;
69
delete foo;
70
}
執行結果
Class1's func1
Class2's func1
若使用C++/CLI,也是可以實現
1
/**/
/*
2
(C) OOMusou 2007
http://oomusou.cnblogs.com
3
4
Filename : Template_test1.cpp
5
Compiler : Visual C++ 8.0 / C++/CLI
6
Description : template test
7
Release : 06/09/2007 1.0
8
*/
9
#include
"
stdafx.h
"
10
11
using
namespace
System;
12
13
interface
class
Interface1
{
14
void
func1();
15
}
;
16
17
interface
class
Interface2
{
18
void
func1();
19
}
;
20
21
ref
class
Class1 :
public
Interface1
{
22
public
:
23
virtual
void
func1()
{
24
Console::WriteLine(
"
Class1's func1
"
);
25
}
26
}
;
27
28
ref
class
Class2 :
public
Interface2
{
29
public
:
30
virtual
void
func1()
{
31
Console::WriteLine(
"
Class2's func1
"
);
32
}
33
}
;
34
35
interface
class
IGeneric
{
36
void
func1();
37
}
;
38
39
template
<
typename T
>
40
ref
class
Generic1 :
public
IGeneric
{
41
private
:
42
T
^
_aClass;
43
44
public
:
45
Generic1(T
^
aClass)
{
46
_aClass
=
aClass;
47
}
48
49
virtual
void
func1()
{
50
_aClass
->
func1();
51
}
52
}
;
53
54
int
main()
{
55
Interface1
^
obj1
=
gcnew Class1;
56
Interface2
^
obj2
=
gcnew Class2;
57
58
IGeneric
^
foo
=
gcnew Generic1
<
Interface1
>
(obj1);
59
foo
->
func1();
60
61
foo
=
gcnew Generic1
<
Interface2
>
(obj2);
62
foo
->
func1();
63
}
執行結果
Class1's func1
Class2's func1
若用C#,以下代碼無法compile成功
1
using
System;
2
3
public
interface
Interface1
{
4
void
func1();
5
}
6
7
public
interface
Interface2
{
8
void
func1();
9
}
10
11
public
class
Class1 : Interface1
{
12
public
void
func1()
{
13
Console.WriteLine(
"
Class1's func1
"
);
14
}
15
}
16
17
public
class
Class2 : Interface2
{
18
public
void
func1()
{
19
Console.WriteLine(
"
Class2's func1
"
);
20
}
21
}
22
23
public
interface
IGeneric
{
24
void
func1();
25
}
26
27
public
class
Generic1
<
T
>
: IGeneric where T : Interface1, Interface2
{
28
private
T _aClass;
29
30
public
Generic1(T aClass)
{
31
_aClass
=
aClass;
32
}
33
34
public
void
func1()
{
35
_aClass.func1();
36
}
37
}
38
39
public
class
main
{
40
public
static
void
Main()
{
41
Interface1 obj1
=
new
Class1();
42
Interface2 obj2
=
new
Class2();
43
44
IGeneric foo
=
new
Generic1
<
Interface1
>
(obj1);
45
foo.func1();
46
47
foo
=
new
Generic1
<
Interface2
>
(obj2);
48
foo.func1();
49
}
50
}
C#無法compile成功
錯誤訊息為
Error 1 The call is ambiguous between the following methods or properties: 'Interface1.func1()' and 'Interface2.func1()' D:\__Clare\CSharp\CSharpLab\Class3.cs 43 5 CSharpLab
Error 2 The type 'Interface1' must be convertible to 'Interface2' in order to use it as parameter 'T' in the generic type or method 'Generic1<T>' D:\__Clare\CSharp\CSharpLab\Class3.cs 52 24 CSharpLab
Error 3 The type 'Interface2' must be convertible to 'Interface1' in order to use it as parameter 'T' in the generic type or method 'Generic1<T>' D:\__Clare\CSharp\CSharpLab\Class3.cs 55 15 CSharpLab
Error1我能理解為什麼不能過,不過並非我故意惡搞,因為實務上的確愈到這樣的需求...
Error2和Error3則真的無法理解了..
看來C#的泛型和C++泛型差異頗大...
請各位指點,該怎麼改才好,改了兩天想不出來...。
<06/16/2007>感謝hyifeng多次的指點,C#的Generics寫法如下
1
/**/
/*
2
(C) OOMusou 2007
http://oomusou.cnblogs.com
3
4
Filename : Generics_Test1.cs
5
Compiler : Visual Studio 2005 / C# 2.0
6
Description : Generics Test
7
Release : 06/16/2007 1.0
8
*/
9
using
System;
10
11
public
interface
InterfaceBase
{
12
void
func1();
13
}
14
15
public
interface
Interface1 : InterfaceBase
{
16
}
17
18
public
interface
Interface2 : InterfaceBase
{
19
}
20
21
public
class
Class1 : Interface1
{
22
public
void
func1()
{
23
Console.WriteLine(
"
Class1's func1
"
);
24
}
25
}
26
27
public
class
Class2 : Interface2
{
28
public
void
func1()
{
29
Console.WriteLine(
"
Class2's func1
"
);
30
}
31
}
32
33
public
interface
IGeneric
{
34
void
func1();
35
}
36
37
public
class
Generic1
<
T
>
: IGeneric where T : InterfaceBase
{
38
private
T _aClass;
39
40
public
Generic1(T aClass)
{
41
_aClass
=
aClass;
42
}
43
44
public
void
func1()
{
45
_aClass.func1();
46
}
47
}
48
49
public
class
main
{
50
public
static
void
Main()
{
51
Interface1 obj1
=
new
Class1();
52
Interface2 obj2
=
new
Class2();
53
54
IGeneric foo
=
new
Generic1
<
Interface1
>
(obj1);
55
foo.func1();
56
57
foo
=
new
Generic1
<
Interface2
>
(obj2);
58
foo.func1();
59
}
60
}
之前C#寫法,主要錯誤為
public
class
Generic1
<
T
>
: IGeneric where T : Interface1, Interface2
我以為是T可以是Interface1 OR Interface2,但實際上是T必須同時implement Interface1 AND Interface2,所以在C#須將相同的Interface提升至InterfaceBase,利用類似多型的方式來處理。
Feedback
#1楼
回复
引用
2007-06-09 16:55 by
hyifeng [未注册用户]
改为
34 public void func1() {
35 ((Interface1)_aClass).func1();
36 }
你要明确你要调用那个接口方法
#2楼
回复
引用
2007-06-09 17:00 by
hyifeng [未注册用户]
concept
where T : Interface1, Interface2
的含义是类型T要同时符合Interface1, Interface2两种约束,而不是二中选一
#3楼
[
楼主
]
回复
引用
查看
2007-06-09 17:02 by
真 OO无双
@hyifeng
concept
where T : Interface1, Interface2
嗯嗯 這也是我懷疑的一個地方
但我的要求是二中選一,那該怎麼改?
#4楼
[
楼主
]
回复
引用
查看
2007-06-09 17:06 by
真 OO无双
@hyifeng
34 public void func1() {
35 ((Interface1)_aClass).func1();
36 }
嗯嗯 這是個方法沒錯
但C#一定得這樣嗎?
你看C++和C++/CLI都不用
#5楼
回复
引用
2007-06-09 17:11 by
hyifeng [未注册用户]
.NET Generic的模板能力比C++差太远。
其实你在C++/CLI中使用还是C++的template。
#6楼
[
楼主
]
回复
引用
查看
2007-06-09 17:18 by
真 OO无双
@hyifeng
.NET Generic的模板能力比C++差太远。
其实你在C++/CLI中使用还是C++的template。
---------
我目前是有考慮ASP.NET用C#寫
但Business Logic Layer用C++/CLI
Data Access Layer用C#
但這樣寫,我怕維護的人會瘋掉
畢竟會C++/CLI的人不是那麼多
所以才希望都用C#
#7楼
回复
引用
2007-06-09 17:21 by
hyifeng [未注册用户]
如无必要 不要用C++/CLI
#8楼
[
楼主
]
回复
引用
查看
2007-06-09 17:25 by
真 OO无双
@hyifeng
如无必要 不要用C++/CLI
---
願聞其詳?
其實我本人還頗喜歡C++/CLI
融合了C# C++ Java VB各家的優點
但我承認這永遠是個小眾的語言
所以我自己會用
但若要跟別人合作的項目,我就不強求用C++/CLI了
#9楼
[
楼主
]
回复
引用
查看
2007-06-09 17:29 by
真 OO无双
@hyifeng
interface ItfBase
{
void func1();
}
interface Itf1 : ItfBase { ... }
interface Itf2 : ItfBase { ... }
public class Generic1<T> : IGeneric where T : ItfBase {
}
---
謝謝你
你的這個方式可以compile成功
結果也如我預期
您剛剛的方式我不小心刪了,請別介意,我原本是想刪除自己的comment
不過總是有一絲絲遺憾...
如
interface a {
void func1();
void func3();
}
interface b {
void func1();
void func2();
}
我想同時支援這兩個interface呢?
#10楼
回复
引用
2007-06-09 17:33 by