Преобразование типов для параметров функции - PullRequest
2 голосов
/ 24 сентября 2010
class A{
};

class B{
public:
    B();
    B(const &A);
};

void foo(A &a){

}

int main(){
   B b;
   foo(b); //error: invalid initialization of reference of type ‘A&’ from expression of type ‘B’
   return 0;
}

В приведенном выше коде у меня ошибка компиляции

ошибка: неверная инициализация ссылки типа 'A &' из выражения типа B

Ошибка может быть решена перегрузкой функции foo ().Тем не менее, есть ли у вас какие-либо другие предложения о том, как я могу решить эту проблему?

Функция foo (A & a) не использует параметр "a" в качестве входных данных.параметр "a" - это просто вывод функции foo (A & a).

спасибо.

Ответы [ 4 ]

3 голосов
/ 24 сентября 2010

Есть много вариантов ... трудно понять, что порекомендовать, не понимая, что пытается ваша программа. Небольшое понимание, которое нам дано в логических отношениях между A и B:

  • только один из конструкторов B требует неконстантной ссылки на объект A
  • foo () предназначен для работы с A или B

это подразумевает, что указатель на A может быть сохранен в B, но напрашивается вопрос: должен ли foo () работать со всеми B (возможно, с использованием построенного по умолчанию A, если ни один не был предоставлен при построении) или только с теми, которые были построены со ссылкой на A?

Варианты дизайна включают в себя:

  • выводит B из A (но ваш конструктор по умолчанию предполагает, что B может существовать, не будучи "привязанным" к A)
  • добавьте A& get_A() и / или const A& get_A() const участника (ов) к class B, затем позвоните foo(b.get_A());
    • сделать это неявно с operator A&() и operator const A&() const
    • вы можете предпочесть A* get_A() и др., Если A необязательно
  • template <class A_or_B> foo(A_or_B&), если A и B предоставляют правильные члены / семантику для foo, чтобы работать на
  • overload foo, предоставляя различные реализации для каждого типа

Исследовательский код:

#include <iostream>

struct A
{
    int n_;
};

void foo(A& a)
{
   a.n_++;
}


struct B
{
    // e.g. B() : p_a_(new A), owner_(true) { } ?
    //      ~B() { if (owner_) delete p_a_; }
    B(A& a) : p_a_(&a) { }

    operator A&() { return *p_a_; }

    A* p_a_;
};

int main()
{
    A a;
    a.n_ = 2;
    B b(a);
    foo(a);
    foo(b);
    std::cout << a.n_ << '\n';
}
0 голосов
/ 24 сентября 2010

Самый простой способ ... если вы хотите назначить объект B в объекте A. Вам нужно увидеть отношения, совместимы они или нет.

Чтобы сделать компиляцию из моей попытки, попробуйте ниже:

class A{ 

}; 

class B: public A{ 
public: 
    B(){
    }
    B(const A&){
    }
}; 

void foo(A &a){ 

}

Надеюсь, это того стоит.

0 голосов
/ 24 сентября 2010

Вы действительно хотите A и B как несвязанные классы? Если классы A и B имеют отношение is-a , то лучше вывести B из A.

class B : public A

, затем также foo(b) с foo (A & a) в качестве сигнатуры приведет к разрезанию объекта.

0 голосов
/ 24 сентября 2010

Проблема в том, что вы пытаетесь неявно преобразовать объект B в объект A. Учитывая, что они предназначены для разделения классов, компилятор не сможет это сделать. Хотя возможно явное приведение указателя или ссылки на объект B к * / & объекта A, это может привести к путанице в компиляторе и является действительно плохой идеей.

Как будто вы просите компилятор преобразовать яблоко в апельсин, не может быть сделано. Если бы B был подклассом A, это было бы вполне возможно. Но вы не можете просто сделать это как обходной путь, если два класса не имеют ничего или мало общего. Однако, если они это делают, и у вас есть несколько связанных классов, создайте базовый класс (содержащий общие методы) и сделайте все эти классы производными от него.

И снова, пожалуйста, не делайте что-то вроде (A*)(&b), потому что это приведет к проблемам во время выполнения, если вы не знаете, какой класс вы фактически получаете в параметре foo () (опять же, если B не выводит из а).

Конечно, лучший способ действий - перегрузить Foo ().

РЕДАКТИРОВАТЬ: вы видите, вы можете преобразовать из A в B в конструкторе B. Но вам нужен A и B, поэтому необходимо ОБРАТНОЕ преобразование. Вот почему ваш текущий код не будет работать.

...