2012-03-14 2 views
3

Попытка воспроизвести то, что в C# вы могли бы сделать что-то вроде этого:Handle неизвестное количество неопределенных объектов для регистрации

string FormatString(params object[] args) { 
     return string.Format(CultureInfo.InvariantCulture, args); 
} 

И в Obj-C это будет выглядеть следующим образом:

#include <stdarg.h> 

void logObjects(id firstObject, ...) { 
    va_list args; 
    va_start(args, firstObject); 
    id obj; 
    for (obj = firstObject; obj != nil; obj = va_arg(args, id)) 
     NSLog(@"%@", obj); 
    va_end(args); 
} 

logObjects(@"foo", [NSNumber numberWithInt:4], @"bar", nil); 

Я знаком с переменной длиной параметра, но не слишком уверен, как хранить аргументы, а затем отправлять их в std :: cout. Возможно ли это?

Внимание! Я хочу отправить любой объект, который может обрабатывать оператор < <. Просто взгляните на эту функцию в качестве замены для:

std::cout << "test" << someObject << int << someOtherObject; 

Я использую boost и хотел бы оставить его независимым от платформы. Эта функция будет частью класса журнала в общей библиотеке lib.

+0

Можете ли вы использовать C++ 11, или вы ограничены C++ 03? – ildjarn

+0

все, что работает на главном os aka nothing ms spec – chikuba

+0

Это не отвечает на мой вопрос вообще. Какой компилятор вы используете? – ildjarn

ответ

1

Извините, но я не очень-то знаю о C#. Вы хотите отправить список параметров в std::cout? Это совсем не сложно:

void formatString (const std::vector<std::string>& args) 
{ 
    for (int i=0; i<args.size(); ++i) 
    { 
     std::cout << args[i]; 
    } 
    std::cout << std::endl; 
} 

И вы можете хранить элементы следующим образом:

std::vector test (2); 
test[0] = "one"; 
test[1] = "two"; 
formatString (test); 

UPDATE

Копировать & Вставить этот код в файл .cpp и скомпилировать его. Вы должны реализовать интерфейс IPrintable для каждого класса, который хотите зарегистрировать. Возможно, это не самое эффективное решение, но оно работает.

#include <iostream> 
#include <string> 
#include <vector> 

class IPrintable 
{ 
public: 
    virtual ~IPrintable() { } 

    virtual std::string toString() const = 0; 
}; 

class ClassA : public IPrintable 
{ 
public: 
    std::string toString() const 
    { 
     std::string s = "Class A to string"; 
     return s; 
    } 
}; 

class ClassB : public IPrintable 
{ 
public: 
    std::string toString() const 
    { 
     std::string s = "Class B to string"; 
     return s; 
    } 
}; 

void print (const std::vector<IPrintable*> args) 
{ 
    for (int i=0; i<args.size(); ++i) 
    { 
     std::cout << args[i]->toString() << std::endl; 
    } 
} 

int main (int argc, char* argv[]) 
{ 
    ClassA a; 
    ClassB b; 

    std::vector<IPrintable*> v (2); 
    v[0] = &a; 
    v[1] = &b; 

    print (v); 
    return 0; 
} 
+2

OP хочет сделать это с ЛЮБОЙ тип данных, а не только строки. На C# все объекты происходят из Object и реализуют (среди прочего) метод .ToString. – Joe

+0

Да, просто любой объект, который имеет оператор << – chikuba

+0

Затем вам нужно перегрузить оператор << для каждого типа, который вы можете записать: 'std :: ostream & operator << (std :: ostream & operator, const SomeType & someObject) ; 'И вам также понадобится базовый класс для хранения разных типов в одном и том же контейнере – user1192525

2

Это не работает на C#, потому что строка формата отсутствует, так или иначе, концепция понятна. В C вы можете сделать что-то вроде этого (как показано в dbgprint, если у вас есть VARIADIC функцию макросъемки)

#define printfex(...) printf(__VA_ARGS__) 

Если вы так повезло использовать C++11 вы можете написать этот прототип:

template<class... T> 
void printfex(const std::string& format, T... args); 
+0

Обратите внимание, что подход '__VA_ARGS__' может работать только с примитивными типами, что делает его почти бессмысленным , – ildjarn

+0

Согласен, но в ** C ** лучше, чем ничего. В C++ он может имитировать Object.ToString() из .NET Framework, если ему нужно что-то большее (это еще более гибко) или использовать stdarg.h с cout. –

+0

Я не имел в виду это как критику вашего ответа, я только думал, что это заслуживает упоминания. : -] – ildjarn

1

Вы не можете использовать переменные параметров run-time в C++ - это основной факт. Вы должны использовать ту же технику, что и потоки C++ - перегрузка оператора. К счастью, C++ уже содержит такую ​​функциональность.

void f(const std::stringstream& str) { 
    std::cout << str; 
} 
int main() { 
    int i = 5; 
    f(std::stringstream() << "i is equal to " << 5); 
} 
+0

как бы это соответствовало моей функции? могу ли я иметь var nr строк? – chikuba

+0

, но спасибо за указание фактов. когда я начал думать об этом, я не знал, как его реализовать. теперь я знаю, что это C++, а не я :) – chikuba

Смежные вопросы