2015-04-27 2 views
3

Рассмотрим этот случай:Неявное приведение C++

ClassA obA; 
ClassB obB; 

obA = obB; 

правильно ли это, что если ClassA имеет конструктор, который имеет параметр типа ClassB, он будет называться в этом случае?

Если есть оператор перегруженного литья в ClassB - который преобразует объект ClassB в объект ClassA, будет вызываться метод оператора. Если есть соответствующий конструктор и перегруженный оператор литья, который будет вызываться? Где я могу прочитать об этом?

+0

Взгляните на этот вопрос, это может помочь вам: http://stackoverflow.com/questions/1092714/conversion-precedence-in-c –

+0

Это не кастинг, это преобразование. – molbdnilo

+0

Как только мы преодолеем путаницу оператора OP с вызовом конструктора, это, похоже, ответит на вопрос: http://stackoverflow.com/questions/1384007/conversion-constructor-vs-conversion-operator-precedence –

ответ

3

Правильно ли, что если ClassA имеет конструктор, который имеет параметр типа ClassB, он будет называться в этом случае?

Да, конструкторы считаются для неявного типа:

Тип преобразования объектов класса могут быть определены с помощью конструкторов и функции преобразования. Эти преобразования называются пользовательскими преобразованиями и используются для неявных преобразований типов (раздел 4), для инициализации (8.5) и для явных преобразований типов (5.4, 5.2.9).

Конструктор с подписью ClassA::ClassA(ClassB) называется превращающего конструктор. Во время вызова функции, такого как назначение, конструкторы и пользовательские операторы преобразования скомпилируются в набор перегрузки и выбирается лучший для преобразования.

Если выбран конструктор: Если тип источника является типом по значению, он создает prvalue типа типа источника (ClassA) инициализирован с типом типа назначения (ClassB), и это используется для инициализации параметра. Если тип источника является ссылкой, используются reference-initialization rules.


Операторы присваивания неявно сгенерированные в ClassA (при условии, что они не были переопределены). Они: последовательность

ClassA& operator=(ClassA const&); 
ClassA& operator=(ClassA  &&); 

неявного преобразования может выбрать либо конструктора или преобразование функции для преобразования из ClassB -> ClassA const& или ClassB -> ClassA&&.

Однако в этом случае переход по вашему сценарию не сможет добиться успеха, поскольку это будет неоднозначно. Рассмотрим:

struct B { operator struct A(); }; 

struct A { 
    A() = default; 
    A(B) {} 
}; 

B::operator A() { return A(); } 

int main() 
{ 
    A a; B b; 
    a = b; // Error! Ambiguous conversion 
} 

Оба A::A(B) и B::operator A() являются жизнеспособные функции преобразования, чтобы использовать для преобразования. Таким образом, преобразование неоднозначно, и нам дается компиляционная ошибка.

Пользовательские преобразования применяются только там, где они недвусмысленны (10.2, 12.3.2).

Если изменить подпись конвертерной-конструктор в классе A к A::A(B const&), то оператор преобразования в B будет использоваться, поскольку конструктор по A «s требует квалификации-преобразование (добавление const).

Существует нить на cppreference, где вы можете узнать больше.

3

Этот код:

ClassA obA; 
ClassB obB; 

obA = obB; 

не то, что вы думаете, это (*). Этот код:

ClassB obB; 
ClassA obA = obB; 

будет работать (как это предусмотрено), если:

1.ClassA имеет конструктор, который принимает в качестве параметра ClassB:

class ClassA 
{ 
public: 
    ClassA(const ClassB& b) 
    { 
     //construct *this from b 
    } 
}; 

2.ClassB определил Оператор преобразования в тип:

class ClassB 
{ 
public: 
    operator ClassA() const 
    { 
     //construct ClassA from *this 
    } 
}; 

Если в ClassA есть оператор перегруженного литья, который имеет параметр типа ClassB [...].

Вы имели в виду конструктор, не произнесения оператора, правильно? Вы пытаетесь преобразовать ClassA в ClassB, поэтому операторы преобразования от ClassA в данном случае неактуальны.


(*) Вы назначаете obB к obA после obA «s конструкции, поэтому в вашем случае только второй пункт применим. Вы также можете заставить его работать, добавив оператор присваивания:

3.

class ClassA 
{ 
public: 
    ClassA& operator=(const ClassB& b) 
    { 
     //assign b to *this 
    } 
}; 

, который будет называться в вашем случае.

+0

Да, это ошибка, я отредактировал вопрос. Спасибо. –

+0

Хороший звонок о # 1.Следует отметить, что если кто-то попробует как # 1, так и # 2, тогда они столкнутся с круглыми проблемами. – AndyG

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