posts - 718, comments - 1240, trackbacks - 51, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

ISO C++

 1/* 
 2(C) OOMusou 2007 http://oomusou.cnblogs.com
 3
 4Filename    : Template_test1.cpp
 5Compiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
 6Description : template test
 7Release     : 06/09/2007 1.0
 8*/

 9#include <iostream>
10
11using namespace std;
12
13class Interface1 {
14public:
15  virtual void func1() = 0;
16}
;
17
18class Interface2 {
19public:
20  virtual void func1() = 0;
21}
;
22
23class Class1 : public Interface1 {
24public:
25  void func1() {
26    cout << "Class1's func1" << endl;
27  }

28}
;
29
30class Class2 : public Interface2 {
31public:
32  void func1() {
33    cout << "Class2's func1" << endl;
34  }

35}
;
36
37class IGeneric {
38public:
39  virtual void func1() = 0;
40}
;
41
42template<typename T>
43class Generic1 : public IGeneric {
44private:
45  T* _aClass;
46
47public:
48  Generic1(T* aClass) {
49    _aClass = aClass;
50  }

51
52  void func1() {
53    _aClass->func1();
54  }

55}
;
56
57int 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
 4Filename    : Template_test1.cpp
 5Compiler    : Visual C++ 8.0 / C++/CLI
 6Description : template test
 7Release     : 06/09/2007 1.0
 8*/

 9#include "stdafx.h"
10
11using namespace System;
12
13interface class Interface1 {
14  void func1();  
15}
;
16
17interface class Interface2 {
18  void func1();
19}
;
20
21ref class Class1 : public Interface1 {
22public:
23  virtual void func1() {
24    Console::WriteLine("Class1's func1");
25  }

26}
;
27
28ref class Class2 : public Interface2 {
29public:
30  virtual void func1() {
31    Console::WriteLine("Class2's func1");
32  }

33}
;
34
35interface class IGeneric {
36  void func1();
37}
;
38
39template<typename T>
40ref class Generic1 : public IGeneric {
41private:
42  T^ _aClass;
43
44public:
45  Generic1(T^ aClass) {
46    _aClass = aClass;
47  }

48
49  virtual void func1() {
50    _aClass->func1();
51  }

52}
;
53
54int 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成功
 1using System;
 2
 3public interface Interface1 {
 4  void func1();
 5}

 6
 7public interface Interface2 {
 8  void func1();
 9}

10
11public class Class1 : Interface1 {
12  public void func1() {
13    Console.WriteLine("Class1's func1");
14  }

15}

16
17public class Class2 : Interface2 {
18  public void func1() {
19    Console.WriteLine("Class2's func1");
20  }

21}

22
23public interface IGeneric {
24  void func1();
25}

26
27public 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
39public 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
 4Filename    : Generics_Test1.cs
 5Compiler    : Visual Studio 2005 / C# 2.0
 6Description : Generics Test
 7Release     : 06/16/2007 1.0
 8*/

 9using System;
10
11public interface InterfaceBase {
12  void func1();
13}

14
15public interface Interface1 : InterfaceBase {
16}

17
18public interface Interface2 : InterfaceBase {
19}

20
21public class Class1 : Interface1 {
22  public void func1() {
23    Console.WriteLine("Class1's func1");
24  }

25}

26
27public class Class2 : Interface2 {
28  public void func1() {
29    Console.WriteLine("Class2's func1");
30  }

31}

32
33public interface IGeneric {
34  void func1();
35}

36
37public 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
49public 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