용오름체험휴양마을영농조합법인 / 홍천 용오름캠핑장 팸투어 다녀왔어요.

용오름체험휴양마을영농조합법인 / 홍천 용오름캠핑장 팸투어 다녀왔어요. 강원도 홍천 서석면에 위치해있으며 1급수 용오름계곡 바로 옆에 있습니다.홍천군 1등 마을로 마을에서 직접 관리하는 용오름캠핑장,펜션 10개를 운영하고 있으며 각종 모임이 가능하도록 식당,회의실,야외무대가 설치되어 있습니다.홍천군 1등 마을답게 캠핑장,펜션 마을 전지역 wi-fi 사용이 가능하며 매년 봄 팸투어 실시, 여름엔 마을에서 재배한 홉으로 직접만든 맥주축제,마리소리 음악축제 를 열고 있습니다.계곡의 경우 수심이 다양하여 다이빙 포인트가 2곳이 있으며 아이들이 안전하게 물놀이를 할 수 있는 곳도 여러 곳 있습니다. 홍천 용오름캠핑장 팸투어 다녀왔어요. 요즘은 농산촌체험마을에서 캠핑과 여러프로그램을 같이 하는 곳이 추세더라고요. 아미산이 둘러쌓인 청정계곡이 흐르는 아름다운 용오름체험휴양마을 에서 운영하는 홍천 용오름캠핑장 팸투어 다녀왔어요. 테크 앞 강이... 붕어빵 가족의 담너머 세상구경 https://m.blog.naver.com/1092119/220711235599 가을여행-홍천여행- 홍천 용오름 마을 첫째날 여행의 계절 가을입니다. 요즘 저희는 강원도에 꽃힌 상태인지라...카페 행복한 이티씨와 함께하는 홍천 용오름 마을 1박2일 체험에 참가를 하였답니다! 평소 체험 시간보다 조금 늦은 출발을 해서 차가 밀리지 않으려나... 귀여운 단지 https://m.blog.naver.com/sanguidan/50181593653 용오름마을 캠핑장 여름휴가의 시즌이다.. 강원도의 계곡과 시원함을 만끽하기 위해 캠핑장을 검색하다 우연히 알게 된 홍천의 용오름 캠핑장.. 성수기라 캠핑장 요금들이 사악하다 용오름캠핑장 옆엔 해미르 캠핑장이 있는데... ★살로몬의 잇츠캠핑★ https://m.blog.naver.com/freeguy9040/20163628934 맥주효모로 만든 용오름맥주마을 바쏘 맥주샴푸와 맥주마스크팩... 1988년까지 맥주 원료인

C++ OOP(Object-Oriented-Programming) (2)

C++ OOP(Object-Oriented-Programming) (2)

복사생성자

생성자 : 객체가 생성될 때 실행될 메소드임

복사생성자 : 같은 클래스에 속한 다른 객체를 이용하여 새로운 객체를 초기화 할때 사용

받는 매개변수가 자신이랑 같은 const& 면 복사생성자

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 //header class Vector1{ public : Vector1(); Vector1( const Vector1 & other); private : int mX; int mY; } //cpp Vector1::Vector1() : mX( 0 ) , mY( 0 ) { } Vector1::Vector1( const Vector1 & other) : mX(other.mX); //other는 다른 인스턴스지만 , mY(other.mY); //같은 클래스형이라서 private에 접근가능함 { } Colored by Color Scripter cs

코드에 복사 생성자가 없는 경우, 컴파일러가 암시적 복사생성자 자동생성

cf) 아무런 생성자도 없으면 기본생성자 + 암시적 복사생성자 만들어줌

하나의 생성자라도 유저가 구현했다면 기본생성자는 만들어주지 않음

암시적 복사 생성자

의미와 특징

- 유저가 구현하지 않아서 컴파일러가 만든 복사 생성자를 암시적 복사생성자라 함

- 암시적 복사 생성자는 "얕은 복사"를 함

- 멤버 별 값 복사

- 멤버변수가 객체라면 그 객체의 복사 생성자도 호출됨

- 만약 heap에 동적할당 후 얕은 복사를 진행하면 문제가 발생할 우려가 있음 (아래코드)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ClassRecord::ClassRecord( const int * scores, int count) : mCount(count) { mScores = new int [mCount]; //동적할당 -> 크기 열어줌 memcpy(mScores, scores, mCount * sizeof ( int )); //복사진행 } ClassRecord::~ClassRecord(){ delete [] mScores; } ClassRecord::ClassRecord( const ClassRecord & other) //암시적 복사생성자와 같음->얕은복사 : mCount(other.mCount) , mScores(other.mScores) // 배열의 시작주소 먹음 { } //main ClassRecord cr(scores, 5 ); //생성자 호출 ClassRecord * crCopy = new ClassRecord(cr); //복사생성자 호출 -> 값만 복사 delete crCopy; //cpCopy의 소멸자 호출 Colored by Color Scripter cs

>>> 메모리 머리속에서 그려보기

-

카피한 객체를 없애는 순간 소멸자가 호출됨

-> 그에 따른 mScores 배열은 없어짐

-> 근데 원본이 여전히 mScores를 가르킴 (문제)

클래스안에서 동적으로 메모리를 할당하고 있다면?

-> 얕은 복사로 인해 위험할 가능성이 높음

-> 직접 복사 생성자를 만들어서 "깊은 복사"를 해야 함

-> 포인터 변수가 가르키는 실제 데이터까지도 복사해야 함(아래코드)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ClassRecord::ClassRecord( const int * scores, int count) : mCount(count) { mScore = new int [mCount]; //동적할당 -> 크기 열어줌 memcpy(mScores, scores, mCount * sizeof ( int )); //복사진행 } ClassRecord::~ClassRecord(){ delete [] mScores; } ClassRecord::ClassRecord( const ClassRecord & other) //깊은 복사 : mCount(other.mCount) { mScores = new int [other.mCount]; memcpy(mScores, other.scores, mCount * sizeof ( int )); } //main ClassRecord cr(scores, 5 ); //생성자 호출 ClassRecord * crCopy = new ClassRecord(cr); //복사생성자 호출 -> 값만 복사 delete crCopy; //cpCopy의 소멸자 호출 Colored by Color Scripter cs

>>> 자세히 보면, 그냥 오버로딩된 생성자와 비슷함

더보기 연습 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 > > > 아래 헤더파일가지고 깊은 복사 해보기 #pragma once namespace test { class String { public : String( const char * str); String( const String & str); ~String(); void Print(); private : char * mString; size_t mSize; }; } > > > 답 #include < iostream > #include "String.h" using namespace std ; namespace test { String::String( const char * str) : mSize(strlen(str) + 1 ) { mString = new char [mSize]; memcpy(mString, str, mSize); } String::String( const String & str) : mSize(str.mSize) { mString = new char [mSize]; memcpy(mString, str.mString, mSize); } String::~String() { delete [] mString; } void String::Print() { cout < < mString < < endl ; } } > > > 메인사용 #include "String.h" #include < iostream > using namespace std ; int main() { test::String str( "123" ); str.Print(); test::String * str2 = new test::String(str); str2 - > Print(); delete str2; str.Print(); } Colored by Color Scripter cs

연산자 오버로딩

함수오버로딩

- 매개변수 목록을 제외하고 모든 게 동일

- 반환형은 달라도 괜찮음

- 근데 매개변수가 같은데 반환형이 다르면 컴파일에러 -> 중복문제

- 매칭되는 것이 하나여야함

- 자료형이 float -> int 가능함 (표준변환)

(C언어 캐스팅): https://dojang.io/mod/page/view.php?id=493

함수 오버로딩 매칭하기

1) void Print(int score);

2) void Print(const char* name);

3) void Print(float gpa, const char* name);

4) int Print(int score); //컴파일 에러 -> 1번과 매칭됨

5) int Print(float gpa);

1) void Print(int score);

2) void Print(const char* name);

3) void Print(float gpa, const char* name);

Print(100); // 1

Print("Pope")l // 2

Print(4.0f, "Pope"); // 3

Print(77.5f); // 1 컴파일 경고가 나올 수 있음

Print("Pope", 4.0f); //컴파일에러

1) void Max(double, double)

2) void Max(int, int)

max(1, 3.14)

>>> 표준변환 1개, 정확한타입 1개 >>> 모호한 호출임 >>> 컴파일에러

>>> 그냥 형변환해서 둘 이상 들어갈 수 있으면 컴파일에러임

cf) 3.14f == float | 3.14 == double

연산자 오버로딩(operator overloading)

단항연산자 : 피연산자 1개

이항연산자 : 피연산자 2개

- C++에서는 연산자 오버로딩을 지원함 (C, Java는 없음)

- 연산자를 오버로딩 하는 방법은 두가지

1) 멤버 함수로 : (클래스 + 연산자 + 매개변수 | ex. Vector1 + Vector1 )

2) 전역 함수로 : (매개변수1 + 연산자 + 매개변수2) | ex. cout << Vector )

-> 좌항이 접근할 수 없는 int형이나 os객체일 때 사용함

- 특정 연산자들은 멤버 함수를 이용해서만 오버로딩 가능

-> =, (), [], -> 등등

1) 멤버 함수로 연산자 오버로딩

- Vector끼리의 연산을 진행하고 싶음

ex) Vector vec = Vector1 + Vector2;

- 멤버 구현쪽으로 가서 연산자 오버로딩 진행

1 2 3 4 5 6 7 Vector1 Vector1:: operator + ( const Vector1 & rhs) { Vector1 retVec; retVec.mX = mX + rhs.mX; retVec.mY = mY + rhs.mY; return retVec; } Colored by Color Scripter cs

1 2 3 4 5 6 7 8 9 10 11 12 #include < iostream > #include "Vector1.h" using namespace std ; int main() { Vector1 vec1( 1 , 1 ); Vector1 vec2( 2 , 2 ); Vector1 vec = vec1 + vec2; cout < < vec.GetX() < < ", " < < vec.GetY(); //3, 3 } Colored by Color Scripter cs

2) 전역 함수로 연산자 오버로딩

- cout << Vector1; 하면 (10, 20)처럼 만들고 싶음 (ex. toString())

- cout에 들어가서 바꾸는 것은 불가능

-> 전역 함수를 만들어 연산자 오버로딩해야 함

-> 전역 함수는 private멤버에 접근할 수 없으므로 friend 키워드 필요

friend

- 클래스 정의 안에 friend 키워드 사용가능

-> 다른 클래스나 함수가 나의 private 또는 protected 멤버에 접근할 수 있게 허용

- friend 클래스

1 2 3 4 5 6 class X{ friend class Y; private : int mPrivateInt; }; // class Y에서 mPrivateInt 접근 가능 해짐 cs

- friend 함수

1 2 3 4 5 6 7 class X{ friend class Y; friend void Foo( const X & x); private : int mPrivateInt; }; // Foo()에서 mPrivateInt 접근 가능 해짐 cs

- cout << Vector1; 를 위한 구현

1 2 3 4 5 6 7 8 9 10 11 12 13 14 //header class Vector1{ friend std ::ostream& operator < < ( std ::ostream & os, const Vector1 & rhs); public : private : int mX; int mY; }; //cpp std ::ostream& Vector1:: operator < < ( std ::ostream & os, const Vector1 & rhs){ os < < rhs.mX < < ", " < < rhs.mY; return os } Colored by Color Scripter cs

cf) 리턴자료형이 ostream& 인 것은 출력의 체이닝을 위함

-> os << Vector1 << endl;

-> 위의 예에서 os << Vector1 이 void라면 void << endl; 은 진행할 수 없음

-> 그래서 os를 반환함

cf) 좌항의 매개변수를 const로 하지 않은 이유는 읽기 전용으로 사용하지 않아서

-> 출력의 상태를 바꿔 버릴수도 있기 때문

cf) friend함수를 작성해야 class 구현부에서 작성하는 전역함수를 main에서 사용할 수 있음

cf) 만약 하지 않으면 컴파일에러

cf) friend함수를 작성하면 외부에서 Vector1:: 로 접근해야함 (11줄 참고)

(정리)전역함수로 연산자오버로딩을 위해서는

header파일에 전역함수를 friend키워드 사용or전역함수선언 -> 하지않으면 main쪽에서 찾지를 못함

1) header에 전역함수를 class멤버말고 전역으로 선언만 -> cpp에서 정의구현

2) header에 friend키워드 사용 -> cpp에서 정의구현

3) main에 사용

연산자 오버로딩과 const

const를 쓰는 이유? (차후 포스팅)

- 멤버 변수의 값이 바뀌는 것을 방지

- 최대한 많은 곳에 const를 붙일 것

-> 일단 const를 붙여서 사용 -> 에러면 바꿔라

- 지역변수(매개변수)에도 마찬가지

const& 를 쓰는 이유?

- 멤버변수가 바뀌고(const) 불필요한 객체의 사본이 생기는 것을 방지(&)

const를 언제 안쓸까?

- 오브젝트의 상태변경이 있을 때 (스트림도 마찬가지)

연산자 오버로딩 제한사항

1. 오버로딩된 연산자는 최소한 하나의 사용자정의 형을 가져야 함

2. 오버로딩된 연산자는 피연산자 수를 동일하게 유지해야 함

3. 새로운 연산자 부호를 만들 수 없음

4. 오버로딩할 수 없는 연산자 존재(. .* :: ?:)

연산자 오버로딩을 남용하지 말 것

- 직관적인 상황에서만 사용하고 직관적이지 못하면 그냥 함수 만들어라

대입 연산자

operator=

- 복사 생성자와 거의 동일 (초기화와 대입의 차이)

-> 복사 생성자는 생성당시에만 호출함

-> (String myStr = originStr : 이것도 복사생성자로 가져감, 선언 후 myStr = originStr으로 호출함)

-> 그래서 대입 연산자는 내가 힙에 가진 메모리를 해제해 줄 필요가 있을 수도

-> 자신이 원래 들고 있던 heap영역 메모리를 해제해야 하기 때문

ex)

MyString a("chararray"); //생성자 호출

MyString b("asdf");

a = b; // 대입연산자 + a가 가지고 있던 heap영역 메모리 해제

- 복사 생성자를 구현했다면 대입 연산자도 구현해야 좋음

-> 하는일이 비슷하니까!

암시적 operator=

- 컴파일러가 자동으로 만들어 줌

- 근데 얕은 대입임

-> 깊은 복사해야 함

암시적 함수

- 암시적 기본 생성자 : 아무런 생성자가 없으면 컴파일러가 만듦

- 암시적 복사 생성자 : 아무런 복사 생성자가 없으면 컴파일러가 만듦(얕은 복사)

- 암시적 소멸자 : 아무런 소멸자가 없으면 컴파일러가 만듦

- 암시적 대입 연산자 : 아무런 소멸자가 없으면 컴파일러가 만듦(얕은 복사)

암시적 함수를 제거하는 법(전통적...)

-암시적 기본 생성자 -> private에 넣어버림, 다른 생성자 구현

-암시적 복사 생성자 -> private에 넣어버림

-암시적 소멸자 -> private에 넣어버림

-암시적 대입 연산자 -> private에 넣어버림

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include < iostream > #include < cstring > #include "Tmp.h" namespace test1 { String::String( const char * str) //"123" : mSize(strlen(str) + 1 ) //"123" + 1 { mString = new char [mSize]; memcpy(mString, str, mSize); } String::String( const String & other) : mSize(other.mSize) { std :: cout < < "call copy structor" < < std :: endl ; mString = new char [mSize]; memcpy(mString, other.mString, mSize); } String::~String() { delete [] mString; } void String::Print() { std :: cout < < mString < < std :: endl ; } void String:: operator = ( const String & rhs) { std :: cout < < "call operator=" < < std :: endl ; mSize = rhs.mSize; delete [] mString; mString = new char [mSize]; memcpy(mString, rhs.mString, mSize); } } Colored by Color Scripter cs

===참고===

Q) 레퍼런스에 대해서 (반환, 매개변수 등등)

Q) const에 대해서 자세히

현재까지 객체지향

- 생성자 오버로딩

- 복사생성자 오버로딩

- 대입연산자 오버로딩

- 소멸자 구현 (가상소멸자)

- 전역함수로 연산자오버로딩해보기

아래 해더파일로 놀아보기

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #pragma once class Test { //friend std::ostream& operator<<(std::ostream& os, const Test& rhs); public : Test( const char * str); Test( const Test & str); virtual ~Test(); void operator = ( const Test & rhs); void Print(); private : char * mTest; size_t mSize; }; std ::ostream & operator < < ( std ::ostream & os, const Test & rhs); cs

from http://malbongcode.tistory.com/56 by ccl(S) rewrite - 2020-03-25 15:54:09

댓글

이 블로그의 인기 게시물

[2020 정보처리기사 실기 - 프로그래밍 언어 활용] 2. 언어 특성 활용...

phpmyadmin 설치 차분히 따라해보자

용오름체험휴양마을영농조합법인 / 홍천 용오름캠핑장 팸투어 다녀왔어요.