2013-07-16 4 views
1

В моем коде C++/CLI у меня есть около 20 различных классов. Я перегрузил функцию print 20 раз, чтобы обрабатывать экземпляр каждого класса. Теперь мне нужно дополнительно поддерживать массивы объектов каждого из этих 20 классов и ненавидеть писать еще 20 перегрузок, которые в основном являются дословными копиями друг друга. В качестве примера, смотри ниже:Использование массива <> в общей функции

void print(int i){ 
    Console::WriteLine("Integer: {0}", i); 
} 

void print(String ^s){ 
    Console::WriteLine(L"Hello " + s); 
} 

generic <typename T> 
void print(array<T> ^ts){ 
    for(int i = 0, n = ts->Length; i < n; ++i) 
    print(ts[i]); 
} 

int main(array<System::String ^> ^args) 
{ 
    array<String^> ^s = gcnew array<String^>{ L"apple", L"ball", L"car" }; 
    print(s); 
    Console::WriteLine(L"Hello World"); 
    return 0; 
} 

Но приведенные выше результаты в следующей ошибки:

error C2665: 'print' : none of the 2 overloads could convert all the argument types 

Почему это не компилировать? Какая альтернатива тому, что я пытаюсь сделать?

+0

Как вы это называете? –

+0

@LightnessRacesinOrbit, я обновил код, включив вызывающую функцию (main) –

+0

Спасибо. Это очень важно. –

ответ

1

Причина, по которой он не компилируется, заключается в том, что универсальные методы, в отличие от методов шаблонов, существуют для всех типов. Методы шаблонов создаются только при их вызове. Поскольку вы вызываете только print со строковым массивом, определение метода шаблона будет компилировать версию, которая явно принимает строковый массив, и ничего больше. Он будет реализован для вызова метода print(String^), и ошибок не будет.

Поскольку он является общим, существует только одна скомпилированная версия метода. Если вы передаете T другому методу, должна быть перегрузка этого метода, который может принимать любой параметр, даже те, которые вы не используете в своей программе. Для этого метода, если вы собираетесь передать T методу, он должен принять параметр типа Object^.

Чтобы выполнить эту работу, я бы выполнил print так, чтобы он взял объект и использовал отражение, чтобы найти имя класса для печати.

void print(Object^ o) 
{ 
    Console::WriteLine("{0}: {1}", o->GetType()->Name, o); 
} 

generic <typename T> 
void print(array<T> ^ts){ 
    for(int i = 0, n = ts->Length; i < n; ++i) 
    print(ts[i]); 
} 

Если вы хотите, чтобы предоставить конкретные версии для конкретных типов, реализовать некоторую дополнительную логику в методе печати:

void print(Object^ o){ 
    if(o->GetType() == String::typeid) 
    Console::WriteLine("Hello {0}", o); 
    else 
    Console::WriteLine("{0}: {1}", o->GetType()->Name, o); 
} 

generic <typename T> 
void print(array<T> ^ts){ 
    for(int i = 0, n = ts->Length; i < n; ++i) 
    print(ts[i]); 
} 
2

Причина, по которой не может быть составлен в том, что нет print<T> функции. Только print функции предназначены для int и String.

шаблон

C++ будет работать:

template <class T> 
void print(array<T> ^ts){ 
    for(int i = 0, n = ts->Length; i < n; ++i) 
    print(ts[i]); 
} 
Смежные вопросы