c++좋 은 프로 그래 밍 습관 과 프로 그래 밍 요점 을 자세히 설명 합 니 다.

1.좋 은 방식 으로 C+class 를 작성 합 니 다.
지금 우리 가 복수 류 complex 를 실현 하고 이러한 실현 과정 에서 좋 은 프로 그래 밍 습관 을 모색 해 야 한다 고 가정 합 니 다.
헤더(헤더 파일)의 방위 식 성명
complex.h:

# ifndef  __COMPLEX__
# define __COMPLEX__
class complex
{
    
}
# endif
헤더 파일 의 내용 이 여러 번 포함 되 는 것 을 방지 합 니 다.
데 이 터 를 private 성명 에 두 고 인터페이스 접근 데 이 터 를 제공 합 니 다.

# ifndef  __COMPLEX__
# define __COMPLEX__
class complex
{
    public:
        double real() const {return re;}
        double imag() const {return im;}
    private:
        doubel re,im;
}
# endif
클래스 속성(데이터 구성원)의 구성원 함 수 를 바 꾸 지 않 습 니 다.모두 const 성명 을 추가 합 니 다.
예 를 들 어 위의 구성원 함수:

double real () `const` {return re;}
double imag() `const` {return im;}
함수 가 대상 을 바 꾸 지 않 는 이상 컴 파일 러 는 함수 의 const 속성 을 확보 하고 코드 를 읽 는 사람 도 의 도 를 명 확 히 할 수 있 습 니 다.
그리고 const 대상 만 이 함수 들 을 호출 할 수 있 습 니 다.-const 대상 은 비 const 구성원 함 수 를 호출 할 수 없습니다.
구조 함수 초기 값 목록 사용 하기

class complex
{
    public:
        complex(double r = 0, double i =0)
            : re(r), im(i)  { }
    private:
        doubel re,im;
}
초기 값 목록 에서 초기 화 합 니 다.구조 함수 안에 있 는 것 을 할당 이 라 고 합 니 다.
매개 변 수 는 가능 한 한 reference to const 를 사용 합 니 다.
complex 클래스 에+=연산 자 를 추가 합 니 다:

class complex
{
    public:
        complex& operator += (const complex &)
}
인용 을 사용 하여 클래스 대상 구조 와 분석 구조의 비용 을 피하 고 const 를 사용 하여 매개 변수 가 바 뀌 지 않도록 합 니 다.내 장 된 유형의 값 전달 과 인용 전달 효율 은 큰 차이 가 없고 심지어 값 전달 효율 이 더욱 높다.예 를 들 어 char 형식 을 전달 할 때 값 전달 은 하나의 바이트 만 전달 해 야 한다.인용 은 실제 포인터 로 이 루어 지 므 로 네 개의 바이트(32 비트 기기)의 전달 비용 이 필요 하 다.그러나 일 치 를 위해 서 는 인용 을 통일 적 으로 사용 하 는 것 도 좋다.
함수 반환 값 도 가능 한 한 인용 을 사용 합 니 다.
인용 방식 으로 함수 부분 변 수 를 되 돌려 주면 프로그램 이 정의 되 지 않 은 행 위 를 일 으 킬 수 있 습 니 다.함수 역할 영역 에서 벗 어 나 부분 변 수 는 소각 되 고 이 변 수 를 참조 하 는 것 은 의미 가 없습니다.그러나 내 가 말 하고 자 하 는 것 은 가능 하 다 면 함 수 는 인용 을 되 돌려 야 한 다 는 것 이다.물론 되 돌아 갈 변 수 는 일정한 제한 이 있어 야 합 니 다.이 변 수 는 함수 에 들 어가 기 전에 메모리 가 할당 되 었 습 니 다.이 조건 을 고려 하면 인용 여 부 를 쉽게 결정 할 수 있다.함수 가 호출 되 었 을 때 만 든 대상 은 인용 을 되 돌려 줄 수 없습니다.
operator+=을 말 하면 그 반환 값 은 인용 입 니 다.왜냐하면 a+=b 를 실행 할 때 a 는 이미 메모리 에 존재 하기 때 문 입 니 다.
한편,operator+의 반환 값 은 인용 할 수 없습니다.a+b 의 값 때문에 operator+를 호출 할 때 만 발생 합 니 다.
다음은 operator+='operator+'와 의 실현 입 니 다.

inline complex & complex :: operator += (const complex & r)
{
    this -> re+= r->re;
    this -> im+= r->im;
    return * this;
}
inline complex operator + (const complex & x , const complex & y)
{
    return complex ( real (x)+ real (y), //      ,      
    imag(x)+ imag(y));
}
operator+=에서 인용 을 되 돌려 주 는 것 이 필요 합 니 다.연속 적 인 동작 을 사용 할 수 있 습 니 다.

c3 += c2 += c1;
조작 부 호 를 다시 불 러 오 면,여러 개의 다시 불 러 올 필요 가 있 는 지 를 고려 합 니 다.
우리 의 복수 류 에 있어+여러 가지 사용 방식 이 있 을 수 있다.

complex c1(2,1);
complex c2;
c2 = c1+ c2;
c2 = c1 + 5;
c2 = 7 + c1;
여러 가지 덧셈 에 대처 하기 위해 서 는 다음 과 같은 세 가지 과부하 가 필요 합 니 다.

inline complex operator+ (const complex & x ,const complex & y)
{
    return complex (real(x)+real(y),
                    imag(x+imag(y););
}
inline complex operator + (const complex & x, double y)
{
    return complex (real(x)+y,imag(x));

inline complex operator + (double x,const complex &y)
{
    return complex (x+real(y),imag(y));
}
외부 에 사용 할 인 터 페 이 스 를 제공 하여 클래스 성명 의 맨 앞 에 놓 습 니 다.
어느 면접 에서 면접 관 형님 이 알려 주 셨 어 요.생각해 보면 확실히 일리 가 있다.이런 사용자 들 은 사용 하기에 도 편 하고 한눈 에 인 터 페 이 스 를 볼 수 있다.
2、Class with pointer member(s)
빅 쓰 리 써 주세요.
C++의 클래스 는 포인터 가 없 는 데이터 멤버 와 포인터 가 없 는 데이터 멤버 두 가지 로 나 눌 수 있 으 며,coplex 는 포인터 가 없 는 멤버 에 속한다.여기 서 말 하고 자 하 는 문자열 클래스 String 은 일반적인 구현 에 char*지침 이 있 습 니 다.포인터 데이터 구성원 의 클래스 는 클 라 스 의 세 가지 큰 부분 을 스스로 실현 해 야 합 니 다.복사 구조 함수,복사 할당 함수,분석 함수 입 니 다.

class String
{
    public:
        String (const char * cstr = 0);
        String (const String & str);
        String & operator = (const String & str);
        ~String();
        char * get_c_str() const {return m_data};
    private:
        char * m_data;
}
복사 구조 함수,할당 구조 함수,분석 함수 가 없 으 면 컴 파일 러 는 기본적으로 한 세트 를 써 줍 니 다.그러나 지침 이 있 는 종 류 는 컴 파 일 러 의 기본 적 인 실현 에 의존 해 서 는 안 된다.이것 은 자원 의 방출,깊 은 복사 와 얕 은 복사 와 관련 된 문제 이다.String 류 를 실현 하 는 과정 에서 우 리 는 이러한 문 제 를 논술 한다.
분석 함수 동적 할당 메모리 자원 방출
클 라 스 에 지침 이 있 으 면 대부분 메모리 동적 할당(예 를 들 어 String)이 필요 합 니 다.분석 함 수 는 대상 의 생명 이 끝 날 때 동적 으로 신청 한 메모 리 를 방출 해 야 합 니 다.그렇지 않 으 면 메모리 유출 이 발생 합 니 다.부분 대상 이 함수 역할 영역 을 떠 날 때 대상 분석 함수 가 자동 으로 호출 되 고 new 동적 으로 분 배 된 대상 도 delete 를 사용 하여 대상 을 삭제 해 야 합 니 다.delete 는 실제 대상 의 석조 함 수 를 호출 합 니 다.석조 함수 에서 포인터 m 를 풀 어야 합 니 다.data 가 신청 한 메모리.다음은 구조 함수 로 m 를 구현 하 였 습 니 다.data 의 동적 메모리 신청:

/*String     */
inline 
String ::String (const char *cstr = 0)
{
    if(cstr)
    {
        m_data = new char[strlen(cstr)+1];   //   ,m_data     
        strcpy(m_data,cstr);
    }
    else
    {
        m_data= new char[1];
        *m_data = '\0';
    }
}
이 구조 함 수 는 C 스타일 문자열 을 매개 변수 로 실행 합 니 다.

String *p = new String ("hello");
m_data 는 시스템 에 메모리 저장 문자열 hello 를 신 청 했 습 니 다.

분석 함 수 는 이 동적 으로 신청 한 메모 리 를 방출 하 는 것 을 책임 져 야 합 니 다.

inline 
String ::~String()
{
    delete[]m_data;
}
할당 구조 함수 와 복제 구조 함수 가 딥 복사 담당
컴 파일 러 를 사용 하여 String 의 기본 값 으로 생 성 된 복사 구조 함수 와 할당 연산 자 를 사용 하면 무슨 일이 일어 나 는 지 살 펴 보 자.기본 복제 구조 함수 나 할당 연산 자가 하 는 일 은 클래스 의 메모 리 를 비트 별로 복사 하 는 것 입 니 다.얕 은 복사 라 고도 부 릅 니 다.대상 메모리 의 모든 bit 를 다른 대상 으로 복사 할 뿐 String 에 서 는 포인터 만 복사 하고 포인터 가 가리 키 는 내용 을 복사 하지 않 습 니 다.현재 String 대상 이 두 개 있 습 니 다:

String a("Hello");
String b("World");
a.b 는 그림 과 같이 메모리 에 있 습 니 다.

하면,만약,만약...

 b = a;
얕 은 복사 본 은 다음 과 같다.

World\0 을 저장 하 는 메모리 블록 은 포인터 가 가리 키 지 않 아 메모 리 를 이용 할 수 없 게 되 어 메모리 유출 이 발생 했 습 니 다.뿐만 아니 라,이 때 대상 a 가 삭제 되면,위 에 쓰 인 분석 함 수 를 사용 하여 Hello\\0 메모리 블록 을 저장 하면 호출 됩 니 다.이때 b.mdata 는 야생 지침 이 되 었 다.우리 가 실현 한 구조 함수 가 이 문 제 를 어떻게 해결 하 는 지 살 펴 보 자.포인터 가 가리 키 는 메모리 내용 을 복사 하 는 것 을 심 복사 라 고 한다.

/*      */
inline String &String ::operator= (const String & str)
{
    if(this == &str)           //①
        return *this;
    delete[] m_data;        //②
    m_data = new char[strlen(str.m_data)+1];        //③
    strcpy(m_data,str.m_data);            //④
    return *this
}
이것 은 복사 할당 함수 의 전형 적 인 실현 입 니 다.요점 은:
① 자기 할당 을 처리 하고 자기 할당 문제 가 없 으 면 다음 절 차 를 계속 합 니 다.
② 자신 이 이미 신청 한 메모 리 를 방출
③ 대상 문자열 과 같은 크기 의 메모리 신청
④ 문자열 복사
a=b,② ③ ④ 과정 은 다음 과 같다.



마찬가지 로 복제 구조 함수 도 깊이 복사 하 는 과정 이다.

inline String ::String(const String & str )
{
    m_data = new char[ strlen (str) +1];
    strcpy(m_data,str.m_data);
}
또한 operator=에서 self assignment 가설 이 이때 대상 의 자기 할당 을 실 행 했 는 지 확인 해 야 합 니 다.좌우 pointers 는 같은 메모리 블록 을 가리 키 고 앞의 단계 ② delete 는 이 메모리 블록 을 제거 하여 다음 결 과 를 가 져 옵 니 다.rhs 메모리 에 접근 하려 고 할 때 결 과 는 정의 되 지 않 았 습 니 다.

3.static 와 클래스
대상 과 직접 관련 이 없 는 데 이 터 는 static 로 성명 합 니 다.
모든 사람 이 은행 계 좌 를 개설 할 수 있 는 은행 계좌 가 있다 고 상상 하 세 요.은행 금 리 라 는 구성원 변수 가 존재 합 니 다.대상 이 아니 라 은행 과 같은 종류 에 속 하고 모든 사용자 가 공유 해 야 합 니 다.static 가 구성원 변 수 를 수식 할 때 이 구성원 변 수 는 프로그램의 전체 영역 에 놓 여 있 고 전체 프로그램 이 실행 되 는 과정 에서 이 구성원 변수의 사본 만 있 습 니 다.일반적인 구성원 변 수 는 모든 대상 의 메모리 에 존재 하 는데 은행 금 리 를 모든 대상 에 두 면 메모 리 를 낭비 하 는 것 이다.
static 멤버 함수 에 이 포인터 가 없습니다.
static 구성원 함 수 는 일반 함수 와 마찬가지 로 하나의 함수 만 있 는 사본 으로 프로 세 스 의 코드 세그먼트 에 저 장 됩 니 다.다른 것 은 static 구성원 함수 에 this 포인터 가 없 기 때문에 일반적인 구성원 변 수 를 호출 할 수 없고 static 구성원 변수 만 호출 할 수 있 습 니 다.일반 구성원 함수 의 호출 은 대상 을 통 해 호출 되 어야 합 니 다.컴 파일 러 는 대상 의 주 소 를 가 져 와 this 포인터 의 실제 인삼 으로 구성원 함수 에 전달 합 니 다.

obj.func() ---> Class :: fun(&obj);
한편,static 구성원 함 수 는 대상 을 통 해 호출 할 수도 있 고 클래스 이름 을 통 해 호출 할 수도 있 습 니 다.
클래스 의 외부 에서 static 구성원 변 수 를 정의 합 니 다.
또 다른 문 제 는 static 구성원 변수의 정의 입 니 다.static 구성원 변 수 는 클래스 외부 에서 정의 해 야 합 니 다:

class A
{
    private:
        static int a; //①
}
int A::a = 10;  //②
① 성명 이 고 ② 가 정의 이 며 변수 가 메모 리 를 분배 한 것 으로 정의 합 니 다.
static 와 클래스 의 작은 응용
이러한 것들 은 면접 에 대처 할 수 있 습 니 다.단일 모델 을 실현 할 때 static 구성원 함수 와 static 구성원 변 수 는 사용 되 었 습 니 다.다음은'굶 주 린 사람 식'이 라 고 불 리 는 단일 모델 의 실현 입 니 다.

class A
{
        public:
            static A& getInstance();
            setup(){...};
        private:
            A();
            A(const A & rhs);
            static A a;
}
클 라 스 A 의 구조 함 수 를 모두 개인 으로 설정 하고 사용자 코드 생 성 대상 을 허용 하지 않 습 니 다."대상 인 스 턴 스 를 가 져 오 려 면 인터페이스 getInstance 를 통 해 가 져 와 야 합 니 다."굶 주 린 사람 식 의 단점 은 코드 가 있 든 없 든 a 가 만들어 진 다 는 것 이다.다음은 개 선 된 단일 모델 로'게으름뱅이 식'이 라 고 합 니 다.

class A
{
    public: 
        static  A& getInstance();
        setup(){....};
    private:
        A();
        A(const A& rsh);
        ...
};
A& A::getInstance()
{
        static A a;
        return a;
}
'게으름뱅이 식'은 진정 으로 a 가 필요 할 때 getInstance 를 호출 해 야 유일한 인 스 턴 스 를 만 들 수 있 습 니 다.이 는 지연 증 을 가 진 단일 모델 로 볼 수 있 으 며 마지막 고비 까지 일 을 하지 않 는 다.많은 디자인 들 이 이러한 지연 사상 을 나 타 냈 다.예 를 들 어 string 이 쓸 때 복사 하고 진정 으로 필요 할 때 만 메모리 가 string 대상 에 게 관리 하 는 문자열 을 분배 한다.
이상 은 c++좋 은 프로 그래 밍 습관 과 프로 그래 밍 요점 에 대한 상세 한 내용 입 니 다.c+좋 은 프로 그래 밍 습관 과 프로 그래 밍 요점 에 관 한 자 료 는 다른 관련 글 에 주목 하 십시오!

좋은 웹페이지 즐겨찾기