Как операторы преобразования работают в C++?

Заполнитель не представляет тегов для себя, таким образом, это является большим для группировки содержания без издержек внешних HTML-тэгов.

Панель действительно имеет внешние HTML-тэги, но действительно имеет некоторые прохладные дополнительные свойства.

  • BackImageUrl: получает/Устанавливает URL фонового изображения для панели

  • HorizontalAlign: получает/Устанавливает
    , выравнивание по горизонтали содержания родителя

  • Переносится: получает/Устанавливает, переносится ли
    содержание панели

существует хорошая статья в startvbnet здесь .

38
задан AraK 20 August 2009 в 18:20
поделиться

6 ответов

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

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

Преобразование во время передачи аргумента

Преобразование во время передачи аргумента будет использовать правила для инициализации копии. Эти правила просто учитывают любую функцию преобразования, не обращая внимания на преобразование в ссылку или нет.

struct B { };
struct A {
  operator B() { return B(); }
};
void f(B);
int main() { f(A()); } // called!

Передача аргумента - это лишь один из контекстов инициализации копии. Другой вариант - «чистая» форма, использующая синтаксис инициализации копирования

B b = A(); // called!

Преобразование в ссылку

В условном операторе преобразование в ссылочный тип возможно, если тип, преобразованный в тип, является lvalue.

struct B { };
struct A {
  operator B&() { static B b; return b; }
};

int main() { B b; 0 ? b : A(); } // called!

Другое преобразование в ссылку - это когда вы напрямую связываете ссылку

struct B { };
struct A { 
  operator B&() { static B b; return b; }
};

B &b = A(); // called!

Преобразование в указатели функций

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

typedef void (*fPtr)(int);

void foo(int a);
struct test {
  operator fPtr() { return foo; }
};

int main() {
  test t; t(10); // called!
}

Иногда эта штука может оказаться весьма полезной.

Преобразование в неклассовые типы

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

struct test {
  operator bool() { return true; }
};

int main() {
  test t;
  if(t) { ... }
}

(преобразование в логическое значение в этом случае можно сделать более безопасным с помощью идиомы safe-bool , запрещающей преобразования в другие целочисленные типы). запускаются везде, где встроенный оператор ожидает определенный тип. Однако конверсия может помешать.

struct test {
  void operator[](unsigned int) { }
  operator char *() { static char c; return &c; }
};

int main() {
  test t; t[0]; // ambiguous
}

// (t).operator[] (unsigned int) : member
// operator[](T *, std::ptrdiff_t) : built-in

Призыв может быть неоднозначным, потому что для участника для второго параметра требуется преобразование, а для встроенного оператора первому требуется преобразование, определяемое пользователем. Два других параметра совпадают соответственно. В некоторых случаях вызов может быть однозначным (тогда ptrdiff_t должен отличаться от int ).

Шаблон функции преобразования

Шаблоны допускают некоторые приятные вещи, но лучше относиться к ним очень осторожно. Следующее делает тип конвертируемым в любой тип указателя (указатели на элементы не рассматриваются как «типы указателей»).

struct test {
  template<typename T>
  operator T*() { return 0; }
};

void *pv = test();
bool *pb = test();
53
ответ дан 27 November 2019 в 03:24
поделиться

Символ "." Оператор не перегружается в C ++. И всякий раз, когда вы говорите xy, преобразование x не будет выполняться автоматически.

16
ответ дан 27 November 2019 в 03:24
поделиться

Преобразования - это не волшебство. Тот факт, что A имеет преобразование в B, а B имеет метод foo, не означает, что a.foo () вызовет B :: foo ().

Компилятор пытается использовать преобразование в четырех ситуациях

  1. Вы явное приведение переменной к другому типу
  2. Вы передаете переменную в качестве аргумента функции, которая ожидает другого типа в этой позиции (здесь операторы считаются функциями)
  3. Вы назначаете переменную переменной другого типа
  4. Вы используете конструкцию копирования переменной или инициализируете переменную другого типа

Есть три типа преобразований, кроме тех, которые связаны с наследованием

  1. Встроенные преобразования (например, int-to-double)
  2. Неявная конструкция, где класс B определяет конструктор, принимающий единственный аргумент типа A, и не помечает его "явным" ключевое слово
  3. Определяемые пользователем операторы преобразования, где класс A определяет оператор B (как в вашем примере)

Как компилятор решает, какой тип преобразования использовать и когда (особенно, когда есть несколько вариантов), это довольно сложно, и я сделал бы плохую работу, пытаясь сжать это в ответ на SO. Раздел 12.3 стандарта C ++ обсуждает неявное построение и определяемые пользователем операторы преобразования.

(Могут быть некоторые ситуации или методы преобразования, о которых я не думал, поэтому прокомментируйте или отредактируйте их, если вы видите, чего-то не хватает)

Я сделал плохую работу, пытаясь сжать это в ответ на SO. Раздел 12.3 стандарта C ++ обсуждает неявное построение и определяемые пользователем операторы преобразования.

(Могут быть некоторые ситуации или методы преобразования, о которых я не думал, поэтому прокомментируйте или отредактируйте их, если вы видите, чего-то не хватает)

Я сделал плохую работу, пытаясь сконденсировать это в ответ на SO. Раздел 12.3 стандарта C ++ обсуждает неявное построение и определяемые пользователем операторы преобразования.

(Могут быть некоторые ситуации или методы преобразования, о которых я не думал, поэтому прокомментируйте или отредактируйте их, если вы видите, чего-то не хватает)

9
ответ дан 27 November 2019 в 03:24
поделиться

Неявное преобразование (с помощью операторов преобразования или неявных конструкторов) происходит при передаче параметров функциям (включая перегруженные операторы и операторы по умолчанию для классов). В дополнение к этому, есть некоторые неявные преобразования, выполняемые с арифметическими типами (поэтому добавление char и long приводит к сложению двух long с длинным результатом).

Неявное преобразование не применяется к объекту, для которого Выполняется вызов функции-члена: для целей неявного преобразования this не является параметром функции.

6
ответ дан 27 November 2019 в 03:24
поделиться

Вы должны сделать

((person)p).think();

Компилятор не имеет информации для автоматического преобразования к человеку, поэтому вам нужно явное преобразование.

Если вы использовали бы что-то вроде

person pers = p;

Тогда у компилятора есть информация для неявного преобразования в person.

Вы можете использовать "преобразование" через конструкторы:

class A
{
public:
   A( int );
};


A a = 10; // Looks like a cast from int to A

Это несколько кратких примеров. Приведение (неявное, явное и т. Д.) Требует дополнительных разъяснений. Вы можете найти подробности в серьезных книгах по C ++ (см. Вопросы о книгах по C ++ о переполнении стека для хороших заголовков, например this ).

0
ответ дан 27 November 2019 в 03:24
поделиться

Компилятор попытается выполнить одно (!) Определенное пользователем приведение (неявный ctor или оператор приведения), если вы попытаетесь использовать объект (ссылку) типа T , где U является обязательным.

. Однако оператор всегда будет пытаться получить доступ к члену объекта (ссылке) на его левой стороне. Просто так это определено. Если вам нужно что-то более необычное, для этого можно перегрузить оператор -> () .

0
ответ дан 27 November 2019 в 03:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: