C++구덩이 밟 기 실전 의 구조 와 분석 함수

머리말
저 는 1 년 동안 연습 한 C++개인 연 습생 입 니 다.포인터,템 플 릿 오류 와 정의 되 지 않 은 행동(undefined behavior)을 좋아 합 니 다.이전에 디자인 모델 의'공장 모델'을 쓸 때 구조,계승 과 new 가 조 합 된 구 덩이 를 발 로 밟 았 는데 지금도 정리 할 시간 이 있다.
구조 함수
알다 시 피 대상 을 만 들 때 일부 구성원 이 초기 화 되 지 않 아 불필요 한 오 류 를 방지 하고 대상 을 만 들 때 구조 함수(성명 형식 없 음)를 자동 으로 호출 하여 구성원 의 초기 화 를 완성 합 니 다.즉:

Class c //   ,      
Class c = Class() //   ,      
Class c = Class("name") //   ,        
Class* c = new Class //   ,      
  • 구조 함수 가 실행 되 기 전에 대상 이 존재 하지 않 습 니 다
  • 구조 함수 가 대상 을 만 든 후 대상 은 구조 함수
  • 를 호출 할 수 없습니다.
  • 클래스 에서 구조 함 수 를 정의 하지 않 으 면 컴 파일 러 는 기본 적 인 구조 함 수 를 제공 하고 매개 변수 가 없 으 며 추가 적 인 문 구 를 실행 하지 않 습 니 다
  • 비 기본 구조 함 수 를 제공 하면 기본 구조 함수 가 없 으 면 오류 가 발생 합 니 다.따라서 어떠한 매개 변 수 를 받 아들 이지 않 는 구조 함 수 를 정의 하고 구성원 에 게 합 리 적 인 값
  • 을 정의 해 야 한다.
  • 일반적으로 기본 구조 함 수 는 모든 종류의 구성원 을 암시 적 으로 초기 화 하 는 데 사용 된다
  • .
  • 자신 이 정의 한 구조 함 수 는 일반적으로 목록 초기 화 를 사용 하여 매개 변 수 를 초기 화 합 니 다
  • 구조 함 수 를 통 해 구성원 에 게 값 을 부여 하 는 것 이 함 수 를 통 해 구성원 에 게 값 을 부여 하 는 것 보다 낫다
  • 
    using namespace std;
    
    class Stone {
    private:
        int weight{0};
        double radius{0.0};
    public:
        Stone() {
            cout << "Class Stone was created by default creator" << endl;
        };
        Stone(int w, double r) : weight{w}, radius{r} {
            cout << "Class Stone was created by custom creator" << endl;
        }
        void showInfo() {
            cout << "Weight: " << this->weight << ", Radius: " 
                 << this->radius << endl;
        }
    };
    
    int main (){
        //   ,      
        Stone s1;
        s1.showInfo();
        //   ,       ,     
        Stone s2 = Stone(12, 3.3);
        s2.showInfo();
        return 0;
    }
    
    
    구조 함수 로 이 루어 진 유형 변환
    다음 코드 를 살 펴 보면 Stone s2 를 발견 할 수 있 습 니 다.s2 = 3.3; 이렇게 double 형식의 데 이 터 를 클래스 형식 에 할당 하 는 것 은 잘못 되 지 않 았 습 니 다.이것 은 암시 적 형식 으로 변 환 됩 니 다.매개 변수 유형 에서 클래스 유형 으로 변 환 됩 니 다.
    
    using namespace std;
    
    class Stone {
    private:
        int weight{0};
        double radius{0.0};
    public:
        Stone() {
            cout << this << endl;
            cout << "Class Stone was created by default creator" << endl;
        };
        //    
        Stone(double r) : radius{r} {
            cout << this << endl;
            cout << "Class Stone was created by parameter radius" << endl;
        }
        Stone(int w) : weight{w} {
            cout << this << endl;
            cout << "Class Stone was created by parameter weight" << endl;
        }
        void showInfo() {
            cout << "Weight: " << this->weight << ", Radius: " 
                 << this->radius << endl;
        }
    };
    
    int main (){
        Stone s2;
        s2 = 3.3;
        s2.showInfo();
        return 0;
    }
    
    
    이것 은 매개 변수의 구조 함 수 를 받 아들 여 할당 문법 을 사용 하여 대상 에 게 값 을 부여 할 수 있 기 때문이다.s2=3.3 은 Stock(double)임시 대상 을 만 들 것 입 니 다.임시 대상 이 초기 화 된 후 구성원 마다 값 을 부여 하 는 방식 으로 대상 에 복사 합 니 다.몇 개의 구조 함수 에 cout<암시 적 전환 에 따 른 위험 을 방지 하기 위해 서 는 키워드 explicit 를 사용 하여 이 기능 을 닫 을 수 있 습 니 다.그러면 매개 변수 유형 에서 클래스 유형 으로 전환 하 는 것 을 명시 적 으로 완성 해 야 합 니 다:s=Stock(1.3).그러나 이의 성 은 없다 는 것 을 보증 해 야 한다.
    
    using namespace std;
    
    class Stone {
    private:
        int weight{0};
        double radius{0.0};
    public:
        Stone() {
            cout << this << endl;
            cout << "Class Stone was created by default creator" << endl;
        };
        //    
        explicit Stone(double r) : radius{r} {
            cout << this << endl;
            cout << "Class Stone was created by parameter radius" << endl;
        }
        explicit Stone(int w) : weight{w} {
            cout << this << endl;
            cout << "Class Stone was created by parameter weight" << endl;
        }
        void showInfo() {
            cout << "Weight: " << this->weight << ", Radius: " 
                 << this->radius << endl;
        }
    };
    
    int main (){
        Stone s2;
        s2 = Stone(3);
        s2.showInfo();
        return 0;
    }
    
    
    상기 코드 에서 Stone(int w)이 닫 히 지 않 으 면 s2=3.3 은 이 구조 함 수 를 호출 합 니 다.그래서 구조 함수 제안 에 explicit 성명 을 추가 합 니 다.
    파생 류 의 구조 함수
    파생 류 가 주의해 야 할 것 은 파생 류 가 구조 되 기 전에 하나의 기본 적 인 구조 함 수 를 호출 하여 기본 적 인 데이터 구성원 의 초기 화 를 완성 하 는 것 이다.기본 대상 은 프로그램 이 파생 류 구조 함수 에 들 어가 기 전에 만들어 진 것 이다.그러면 초기 화 목록 을 통 해 기본 매개 변수 에 전달 할 수 있 습 니 다.전달 하지 않 으 면 기본 클래스 의 기본 구조 함 수 를 호출 할 수 있 습 니 다.예 를 들 어 다음 프로그램의:Gem(){}:Stone().
    
    using namespace std;
    
    class Stone {
    private:
        int weight{0};
        double radius{0.0};
    public:
        Stone() {
            cout << "This object was in address: " << this << endl;
        };
        Stone(int w, double r) : weight{2}, radius{r} {};
        void showInfo() {
            cout << "Weight: " << this->weight << ", Radius: " << this->radius;
        }
        int getWeight(){
            return this->weight;
        }
        auto getRadius() -> double {
            return this->radius;
        }
    };
    
    class Gem : public Stone {
    private:
        double price;
    public:
        Gem(){};
        Gem(double p, int w, double r) : Stone(w, r), price{p} {};
        void show() {
            cout << "Weight: " << this->getWeight() << ", Radius" 
                 << this->getRadius();
        }
    };
    
    int main (){
        Gem g1; // call default
        Gem g2 = Gem(1300, 1, 2.3); // call custom 
        // g.setWeight(130);
        g2.show();
        return 0;
    }
    
    
  • 우선 기본 클래스 대상 만 들 기
  • 파생 류 는 초기 화 목록(구조 함수 에 만 사용 가능)을 통 해 기본 정 보 를 기본 클래스 에 전달 하 는 구조 함수
  • 파생 류 구조 함 수 는 파생 류 에 새로운 구성원 을 초기 화 할 수 있다.
  • 분석 함수
    대상 이 만 료 될 때 프로그램 은 대상 의 분석 함 수 를 호출 하여 정리 작업 을 완성 합 니 다.예 를 들 어 변 수 를 방출 하여 열 린 공간 등 입 니 다.구조 함수 가 new 를 사용 하여 공간 을 신청 하면 분석 구 조 는 delete 로 공간 을 방출 해 야 합 니 다.분석 함 수 를 특별히 설명 하지 않 으 면 컴 파일 러 는 클래스 에 기본 적 인 분석 함 수 를 제공 하고 대상 역할 영역 이 만 료 되 고 삭 제 될 때 자동 으로 호출 됩 니 다.
    예 를 들 어 stock 1=Stock()은 임시 변 수 를 신 청 했 고 변수 가 사라 질 때 분석 함 수 를 호출 합 니 다.그 밖 에 이런 부분 변 수 는 스 택 에 두 고 먼저 들 어간 후에 나 오 는 것 이다.즉,마지막 에 신청 한 변수 가 가장 먼저 풀 려 난 것 이다.
    
    using namespace std;
    
    class Stone {
    private:
        int weight{0};
        double radius{0.0};
    public:
        Stone() {
            cout << "This object was in address: " << this << endl;
        };
        ~Stone() {
            cout << this << " Object was deleted." << endl;
        }
    };
    
    int main (){
        {
            Stone s1;
            Stone s2;
        }
        return 0;
    }
    
    
    계승 중인 분석 함수
    상속 류 는 비교적 이해 하기 쉬 운 데,어쨌든 모두 대상 을 향 해 배 운 적 이 있 기 때문이다.공유 상속 을 할 때 기류 의 공유 구성원 도 파생 류 의 공유 구성원 이다.사유 구성원 도 파생 류 의 일부분 이지 만 공유 또는 보호 방법 으로 방문 해 야 한다.그러나 파생 류 와 기류 의 석조 함수 사이 도 구덩이 다.상속 중:
  • 한 방법 이 가상 방법 이 아니라면 인용 유형 이나 포인터 유형 에 따라 실행 방법 을 선택 합 니 다
  • 한 가지 방법 이 가상 방법 이 라면 지침 이나 대상 을 가리 키 는 유형 에 따라 실행 방법 을 선택 합 니 다.
  • 상속 에서 대상 의 소각 순 서 는 창설 과 상반 된다.만 들 때 기본 클래스 를 만 들 고 하위 클래스 를 만 듭 니 다.소각 할 때,먼저 하위 클래스 의 분석 함 수 를 호출 한 후,기본 클래스 의 분석 함 수 를 자동 으로 호출 합 니 다.따라서 기본 클래스 에 서 는 석조 함 수 를 가상 방법 으로 쓰 는 것 을 권장 합 니 다.만약 에 분석 구조 가 가상 방법 이 아니라면 다음 과 같은 상황 에 대해 기본 적 인 분석 구조 만 호출 된다.만약 에 분석 구조 가 가상 방법 이 라면 하위 류,기본 류 의 분석 구조 방법 이 모두 호출 된다.다음 코드 의 virtual 을 삭제 하여 결 과 를 관찰 할 수 있 습 니 다.
    
    using namespace std;
    
    class Stone {
    private:
        int weight{0};
        double radius{0.0};
    public:
        Stone() {
            cout << "This object was in address: " << this << endl;
        };
        Stone(int w, double r) : weight{2}, radius{r} {};
        void showInfo() {
            cout << "Weight: " << this->weight << ", Radius: " 
                 << this->radius;
        }
        int getWeight(){
            return this->weight;
        }
        auto getRadius() -> double {
            return this->radius;
        }
        virtual ~Stone() {
            cout << "Stone class was deleted." << endl;
        }
    };
    
    class Gem : public Stone {
    private:
        double price;
    public:
        Gem() {};
        Gem(double p, int w, double r) : Stone(w, r), price{p} {};
        void show() {
            cout << "Weight: " << this->getWeight() << ", Radius" 
                 << this->getRadius();
        }
        ~Gem() {
            cout << "Gem class was deleted." << endl;
        }
    };
    
    int main (){
        Stone* s1 = new Gem(2.3, 2, 3.2);
        delete s1;
        // Gem* g1 = new Gem(2.3, 2, 1.2);
        // delete g1;
        return 0;
    }
    
    
    활용 단어 참조
    아마 흔히 볼 수 있 는 구 덩이 는 위 에 기록 되 어 있 을 것 이다.내 가 쓴 위험한 프로그램(나 는 대충 추상 화 했다)을 보면 야생 지침 과 정의 행 위 를 덮 었 다.
    
    using namespace std;
    
    class A {
    private:
        int* a;
    public:
        int* create() {
            a = new int();
            return a;
        }
        ~A(){
            delete a;
        }
    };
    
    int main () {
        A a;
        int* b = a.create();
        delete b;
        return 0;
    }
    
    
  • create 를 호출 할 때마다 new 가 한 번 씩 있 지만 delete 만 한 번 있 습 니 다.
  • create 직접 분석 구 조 를 호출 하지 않 으 면 정의 되 지 않 은 행위
  • 만약 에 b 가 a.create()의 지침 을 가지 고 a 가 미리 구 조 를 분석 하면 b 는 야생 지침
  • 이다.
  • delete b 는 필요 없습니다.이렇게 하면 double free 이자 정의 되 지 않 은 행위
  • 상기 코드 는 구역 분류 없 이 new 와 되 돌아 오 는 것 을 어디서 삭제 해 야 합 니까?
  • 클래스 로 하여 금 이 new 를 관리 하 게 할 수 있 습 니 다.create 의 실현 을 수정 하거나 아예 new 를 구성 하거나 delete
  • 를 분석 할 수 있 습 니 다.
    총결산
    C++구덩이 밟 기 실전 의 구조 와 석조 함수 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 C++구조 와 석조 함수 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기