Неявные аргументы конструктора - PullRequest
5 голосов
/ 16 февраля 2012

Я всегда думал, что неявный конструктор в C ++ может быть только конструктором с одним аргументом. Например:

class Foo1
{
   Foo(int); // This could be an implicit constructor
};

Но следующий код правильный:

class Foo2
{
    Foo2(int, int=0);  // Would compiler use this as an implicit constructor?
}

Я могу сделать это:

Foo1 obj;
...
obj = 5;

А как же Foo2?

Ответы [ 4 ]

7 голосов
/ 16 февраля 2012

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

После этого вам просто необходимо понять, что на самом деле означает explicit. Это просто означает, что единственный способ вызова конструктора - это когда вы явно указываете имя класса:

struct foo
{
    foo(int){}
    explicit foo(double){}
};

void bar(foo){}

bar(5); // okay, calls foo(int) to construct the foo
bar(3.14); // error, cannot call foo(double) because foo was not explicitly used
bar(foo(3.14)); // okay, calls foo(double) to construct the foo

Причина, по которой мы не помечаем конструкторы с несколькими аргументами явными, заключается в том, что они бесполезны. Дано:

struct baz
{
    baz(int, int, int);
};

Как еще можно вызвать этот конструктор, кроме как сказать baz? (Как в baz(1, 2, 3).) †

В вашем примере explicit было бы разумно, потому что вы могли бы вызвать этот конструктор только с одним аргументом. То, что вы на самом деле делаете, зависит только от того, считаете ли вы, что оно должно быть неявно конвертируемым или нет.


† Это не относится к спискам инициализаторов C ++ 11. В C ++ 11, я думаю, вы могли бы сказать:

void qaz(baz) {}

qaz({1, 2, 3}); 

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

2 голосов
/ 16 февраля 2012

Если я понимаю, что вы спрашиваете, тогда ответ - да.

Если быть более точным, то, по сути, любой ctor, который может быть вызван только с одним аргументом, может и будетиспользуется для неявных преобразований.Чтобы предотвратить это, такой ctor может быть помечен explicit.Это в равной степени относится к ctor, который принимает только один аргумент или тот, который может принимать более одного аргумента, но предоставляет значения по умолчанию для других аргументов.

1 голос
/ 16 февраля 2012

То, что вы, вероятно, имели в виду, это неявные конструкторы, а не явные .

В любом случае, вы не можете сделать это (в отличие от того, что, как вы думаете, вы можете):

Foo1 obj; //this line will not compile as it takes one argument!
obj = 5;

Я уверен, что вы не скомпилировали свой код, прежде чем сказать, что можете это сделать.

Однако, если вы это имели в виду,

Foo1 obj(10); //OK now
obj = 5;

Тогда да, вы можете.

А как насчет Foo2?Ну, вы можете сделать это и в случае Foo2:

Foo2 foo(10);
foo = 5;
1 голос
/ 16 февраля 2012

Вы путаете EXplicit и IMplicit здесь.Вы говорите о конструкторах преобразования.Явный конструктор как раз наоборот: тот, который не может использоваться для (неявных) преобразований.

И чтобы ответить на ваш вопрос: да, Foo2(int, int=0) - это конструктор преобразования, который позволяет неявнымпреобразование, как в obj = 5, потому что его можно вызвать с одним int аргументом.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...