프로그래밍/C++

[C++] explicit 생성자

갓똥 2019. 11. 6. 00:25
728x90
반응형

1. explicit 생성자(1)

#include <iostream<

class OFile {
    FILE* file;
public:
    OFile(const char* filename) {
        file = fopen(filename, "wt");
    }
    ~OFile() { fclose(file); }
};

int main() {
    OFile f1("a.txt");  // 직접 초기화
    OFile f2 = "a.txt"; // 복사 초기화
}

  객체를 초기화 하는 방법

 

#include <iostream<

class OFile {
    FILE* file;
public:
    OFile(const char* filename) {
        file = fopen(filename, "wt");
    }
    ~OFile() { fclose(file); }
};

void tmp(Ofile f) {}

int main() {
    OFile f1("a.txt");  // 직접 초기화
    OFile f2 = "a.txt"; // 복사 초기화
    
    tmp(f1);      // ok
    tmp("hello"); // error?
}

 

첫 번째 코드는 아무 문제 없이 잘 실행된다.
두 번째 코드에서는 OFile 타입의 f를 인자로 받는 tmp함수가 추가 되었고, main함수에서 tmp함수를 호출했다.
tmp(f1);은 문제가 없어보인다.
그렇다면 tmp("hello"); 는 문제가 있을까?
얼핏 봐서는 잘 못 입력한 사례이고, 에러가 나는게 맞아 보이지만 컴파일 해보면 문제가 없다.
왜냐하면 실제 코드에선 인자로 받을 때 OFile f = "hello"; 로 받기 때문에 복사 초기화로 되어 문제없이 컴파일 된다.

  함수 인자 전달과 초기화 방법

    => 함수 인자 전달 시 복사 초기화를 사용한다.

    => 특정 클래스 설계 시 복사 초기화를 사용하지 못하게 하는 것이 좋을 때가 있다.

 

  - 이제 아래에서 위의 코드의 문제를 해결해보자.

 


2. explicit 생성자(2)

#include <iostream<

class OFile {
    FILE* file;
public:
    explicit OFile(const char* filename) {
        file = fopen(filename, "wt");
    }
    ~OFile() { fclose(file); }
};

void tmp(Ofile f) {}

int main() {
    OFile f1("a.txt");  // ok
    OFile f2 = "a.txt"; // error
    
    tmp(f1);      // ok - 복사 생성자
    tmp("hello"); // error
}

   객체를 초기화 할 때 직접 초기화 만 사용할 수 있고, 복사 초기화는 사용할 수 없다.

 

   Ofile의 생성자가 explicit 이고, tmp함수가 Ofile을 인자로 가지는 경우

 


3. C++ 표준 라이브러리와 explicit 생성자

#include <iostream>
#include <vector>
#include <string>
#include <memory>

int main() {
    std::string s1("hello");  // ok
    std::string s2 = "hello"; // ok
    
    std::vector<int> v1(10);    // ok
    std::vector<int> v2 = 10;   // error
    std::vector<int> v3 = {10}; // ok
    
    // C++ 표준 스마트 포인터
    std::shared_ptr<int> p1(new int);  // ok
    std::shared_ptr<int> p2 = new int; // error
}

  ① string 클래스

    => 아무 문제 없이 컴파일 된다.

    => 생성자가 explicit가 아니다.

 

   vector

    => 복사 초기화를 하면 에러가 난다.

    => 생성자가 explicit이다.

    => v3는 문제 없이 컴파일 된다. : v2에서 호출되는 생성자와 v3에서 호출되는 생성자는 다른 생성자다.

 

  ③ C++ 표준 스마트 포인터

    => 복사 초기화를 하면 에러가 난다.

    => 생성자가 explicit이다.

728x90
반응형