여러 인수를 사용하는 명시 적 생성자


88

여러 인수를 갖는 생성자를 만드는 것이 explicit(유용한) 효과가 있습니까?

예:

class A {
    public:
        explicit A( int b, int c ); // does explicit have any (useful) effect?
};

답변:


120

C ++ 11까지는 explicit다중 인수 생성자 에서 사용할 이유가 없습니다 .

이니셜 라이저 목록으로 인해 C ++ 11에서 변경됩니다. 기본적으로 이니셜 라이저 목록을 사용한 복사 초기화 (직접 초기화는 아님)에는 생성자가 표시되지 않아야합니다 explicit.

예:

struct Foo { Foo(int, int); };
struct Bar { explicit Bar(int, int); };

Foo f1(1, 1); // ok
Foo f2 {1, 1}; // ok
Foo f3 = {1, 1}; // ok

Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY

5
나는이 대답이 "내가 왜 그것을 원 할까"또는 "이것이 유용 할 때"설명과 함께 더 나을 것이라고 생각한다.
MateuszL

@MateuszL Edgar의 대답은 아마도 그것이 왜 유용 할 수 있는지에 대한 최고의 주장을 제공합니다 (그리고 틀림없이 진드기를받을만한 가치가 있습니다). 그러나 그것이 존재 하는 이유 는 단순히 기존 의미 체계의 논리적 확장이기 때문입니다 explicit. 나는 개인적으로 다중 인수 생성자를 만드는 데 신경 쓰지 않을 것 explicit입니다.
Sneftel

31

중괄호 초기화를 위해 우연히 발견했습니다 (예 : 배열)

struct A {
        explicit A( int b, int c ) {}
};

struct B {
         B( int b, int c ) {}
};

int main() {
    B b[] = {{1,2}, {3,5}}; // OK

    A a1[] = {A{1,2}, A{3,4}}; // OK

    A a2[] = {{1,2}, {3,4}}; // Error

    return 0;
}

24

@StoryTeller와 @Sneftel의 훌륭한 답변이 주된 이유입니다. 그러나 IMHO, 이것은 나중에 코드가 변경 될 때 향후 교정의 일부로 의미가 있습니다 (적어도 나는 그렇게합니다). 귀하의 예를 고려하십시오.

class A {
    public:
        explicit A( int b, int c ); 
};

이 코드는 explicit.

얼마 후에 대한 기본값을 추가하기로 결정 c하면 다음과 같이됩니다.

class A {
    public:
        A( int b, int c=0 ); 
};

이 작업을 수행 할 때 c매개 변수에 초점을 맞추게됩니다. 돌이켜 보면 기본값이 있어야합니다. A자신이 암시 적으로 구성되어야 하는지 여부에 반드시 초점을 맞추는 것은 아닙니다 . 안타깝게도이 변경 사항은 explicit다시 의미가 있습니다.

따라서 ctor가임을 전달하기 위해 explicit메서드를 처음 작성할 때 그렇게하는 것이 좋습니다.


하지만 관리자가 기본값을 추가하고 그 결과 변환 생성자로 사용할 수 있어야한다고 결론을 내리는 경우 어떻습니까? 이제 그들은 영원히 존재 했던 것을 제거 해야 explicit하고, 기술 지원은 그 변화에 대한 전화로 넘쳐날 것이며 , 그저 소음 일 뿐이며 제거하는 것이 무해하다고 설명하는 데 시간을 할애 explicit할 것입니다. 개인적으로 저는 미래를 잘 예측하지 못합니다. 이제 인터페이스가 어떻게 생겼는지 결정하기가 어렵습니다 .
Pete Becker

@PeteBecker 좋은 지적입니다. 저는 개인적으로 두 경우가 비대칭이라고 생각하며, 매개 변수를 기본값으로 설정 (또는 제거) 할 때 실수로 클래스를 암시 적으로 구성 할 수있게 한 다음 실제로 돌이켜 보면 그렇게되어야한다는 사실을 실제로 깨닫는 것이 훨씬 더 일반적이라고 생각합니다. 즉, 이는 "부드러운"고려 사항이며 사람 / 프로젝트 / 등간에 다를 수 있으며 심지어 취향의 문제 일 수도 있습니다.
Ami Tavory

8

이 토론에 대한 나의 5 센트는 다음과 같습니다.

struct Foo {
    Foo(int, double) {}
};

struct Bar {
    explicit Bar(int, double) {}
};

void foo(const Foo&) {}
void bar(const Bar&) {}

int main(int argc, char * argv[]) {
    foo({ 42, 42.42 }); // valid
    bar({ 42, 42.42 }); // invalid
    return 0;
}

쉽게 볼 수 있듯이 의 생성자가 으로 선언되어 있기 때문에 함수 explicit와 함께 이니셜 라이저 목록을 사용하지 bar않습니다 .struct Barexplicit

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.