2016-01-29 4 views
2

Я уверен, что ответ отрицательный, но так как это было бы прекрасно, я все равно задам вопрос.Можно ли умножать аргумент функции?

Пример:

class Serializable 
{ 
public: 

    virtual void serialize() = 0; 
}; 

class Unserializable 
{ 
public: 

    virtual void unserialize() = 0; 
}; 

class A : public Serializable 
{ 
public: 

    virtual void serialize() 
    { 
    } 
}; 

class B : public A, public Unserializable 
{ 
public: 

    virtual void unserialize() 
    { 
    } 
}; 

Теперь, есть какой-то способ создать функцию с одним аргументом, который является как экземпляр Serializable и Unserializable таким образом, что объект класса B может быть передан (без, конечно, ссылки на производный тип B)? Что-то вроде:

void readAndWrite(Serializable_Unserializable& object); 
+0

Нет, нет, но вы можете легко передать два параметра и получить более полезную функцию в сделке. – molbdnilo

+0

Не думал так, и, хотя я полагаю, что это правда, в моем фактическом использовании это может привести к множеству параметров, в то время как концептуально для всех из них будет передан только один объект. –

+0

Большое спасибо за быстрый комментарий! –

ответ

3

Шаблоне путь:

template <typename T> 
std::enable_if_t<std::is_base_of<Serializable, T>::value 
       && std::is_base_of<Unserializable, T>::value> 
void readAndWrite(T& object) 
+0

Я понял, что это невозможно, и это вроде как, но это отличный обходной путь! –

3

Конечно, если вы можете изменить B (и любой другой производный тип, который должен наследовать оба), чтобы получить единый интерфейс, который наследует оба интерфейса, и не против виртуального наследования:

class Serializable_Unserializable: 
    public virtual Serializable, 
    public virtual Unserializable 

Виртуальное наследование также должно быть добавлено к A и любому другому классу, который наследует один из двух базовых интерфейсов и может наследоваться классом, который также наследует объединенный интерфейс.

class A: public virtual Serializable 

Теперь вы можете изменить B к:

class B: public A, public Serializable_Unserializable 

И он может быть передан на ваш void readAndWrite(Serializable_Unserializable& object).

Без этих изменений я не думаю, что вы можете определить функцию, которая будет принимать только объекты, которые наследуют оба отдельных интерфейса, но позволяет определять тип во время выполнения. Если последнее не является жестким требованием, то шаблоны будут альтернативой.

+0

Это хороший ответ, но он пропустил одну точку: классы A и B также могут реализовывать другие интерфейсы, которые могут быть полезны для использования в качестве аргументов для других функций, что станет довольно сложным для управления. –

+0

@ JonVance хорошо, сериализуемый и неэриализуемый - это довольно тесно связанные интерфейсы, и их объединение может иметь смысл. Но для всех, не связанных между собой интерфейсов, это не будет хорошо масштабироваться.Если это необходимо, я бы использовал шаблон, или если требуется полиморфизм времени выполнения, используйте отдельные аргументы, даже если разные аргументы ссылаются на тот же объект, что и предложенный molbdnilo. – user2079303

1

Вы могли бы рассмотреть возможность использования dynamic_cast, если вы не против выполнения накладных расходов поиска VMT объекта, чтобы увидеть, если Unserializable поддерживается:

void readAndWrite(Serializable& object) 
{ 
    Unserializable *uobject = dynamic_cast<Unserializable*>(&object); 
    if (uobject) { 
     // supported ... 
    } else { 
     // not supported ... 
    } 
} 
Смежные вопросы