доступ к приватному конструктору по классу друга

Проблема: исходный код (см. Ниже) скомпилирован MSVC, но не компилирует g ++.

#include <iostream>
using namespace std;

class B;
class A
{
friend class B;

private:
int i;
A(int n) : i(n) { }

public :
A(A& a) {   if (&a != this) *this = a;  }
int display() { return i;}
};

class B
{
public :
B() { }
A func( int j)  {  return A(j); }
};

int main(int argc, char **argv)
{
B b;
A a(b.func((10)));
cout << " a.i = " << a.display() << endl;

return 0;
}

Выход:

GNU g++ compilation message:
g++ -c main.cpp
main.cpp: In member function 'A B::func(int)':
main.cpp:25:38: error: no matching function for call to 'A::A(A)'
A func( int j)  {  return A(j); }
^
main.cpp:25:38: note: candidates are:
main.cpp:17:9: note: A::A(A&)
A(A& a) {   if (&a != this) \*this = a;  }
^
main.cpp:17:9: note:   no known conversion for argument 1 from 'A' to 'A&'
main.cpp:14:9: note: A::A(int)
A(int n) : i(n) { }
^
main.cpp:14:9: note:   no known conversion for argument 1 from 'A' to 'int'
main.cpp: In function 'int main(int, char\**)':
...

Зачем? Class B это friend за class A затем B имеет доступ к частному конструктору A(int i),

1

Решение

Ваш конструктор копии должен взять const ссылка, чтобы он мог привязать к временному A:

 A(const A& a) { .... }

Стандарт C ++ не позволяет привязывать неконстантную ссылку к временной. G ++ строго относится к этому, в то время как у MSVC есть «расширение», которое нарушает правило.

Кроме того, ваша реализация конструктора копирования выглядит странно. Вы не должны использовать оператор присваивания там. Для класса, как A, вы должны использовать неявно сгенерированный конструктор копирования, другими словами, удалить свой собственный:

class A
{
friend class B;
private:
int i;
A(int n) : i(n) { }

public :
int display() const { return i;}
};
3

Другие решения

Это ошибка MS VC ++. Он не должен компилировать код. Проблема в том, что сообщение об ошибке g ++ недостаточно ясно.

Фактически, компилятор пытается исключить использование конструктора копирования и построить объект непосредственно в ‘a’, используя конструктор A (int n) ;. Но это будет возможно, соответствующий конструктор копирования будет доступен. Поскольку временный объект должен быть скопирован (если не будет использовано изображение), тогда конструктор копирования должен иметь константную ссылку на объект. То есть вместо А (А& а); ваш конструктор копии должен быть объявлен как A (const A& а); Если вы внесете изменения, g ++ скомпилирует код.

Самый простой способ определить конструктор копирования для вашего примера — написать

A( const A & ) = default;

Однако я не уверен, поддерживает ли ваш компилятор MS VC ++ эту функцию.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector