C++ 7주차 수업 내용 및 수업 후 과제

2024. 10. 15. 11:04C++프로그래밍/수업 내용 및 수업 후 과제

반응형

- 클래스 외부에서 멤버에 접근할 수 있는 권한
 전용(private)
   해당 클래스 내부에서만 접근 가능
   디폴트 속성으로 생략 가능(써도 되고 안써도 됨)
 범용(public)
   어디에서나 접근 가능
 보호(protected)
   private이지만 자식에게는 접근할 수 있도록 함

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

디폴트로 설정되어 있는 것

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

- 클래스 맴버의 접근 권한 :  public(범용)

함수는 보통 public으로 만듬(맴버함수는 주로 public으로 선언)

 public의 멤버함수는 private 멤버변수를 접근하는데 많이 사용
 private 멤버변수 age에 접근하기 위해 getAge()라는 멤버함수
 age의 값에 접근하려고 하면 getAge()라는 함수를 통해야 함
 coco.getAge()

 

예시

class Dog{
 private:         // 여기부터는 private
  int age;         // 멤버변수
  public:          // 여기부터는 public
int getAge(); // 멤버함수
}; 
Dog coco;    // 객체

 

함수 만드는 것은 중요함, 중간고사에 나옴

예시)

#include <iostream>
class Dog {
private:
int age;
public:
int getAge() {
return age;
}
void setAge(int a) { // 입력하는 함수, return값이 없기 때문에 void를 씀 a는 parameter
age = a;
}
};
int main()
{
Dog coco;
coco.setAge(3); //a에 넣을 값을 ()에 넣음 3은 argument
std::cout << coco.getAge() ;
}

a는 parameter, 3은 argument 중요!!

 

함수 선언 정의 호출까지 써서 하는 두번째 방법
두가지 방법 모두 알아둬야하고 중간고사 50점짜리 문제 아래쪽에 다시 한번 정리
#include <iostream>
class Dog {
private:
int age;
public:
int getAge();
void setAge(int a);
};
int Dog::getAge() {
return age;
}
void Dog::setAge(int a) {
age = a;
}
int main()
{
Dog coco;
coco.setAge(3);
std::cout << coco.getAge() ;
}

 

중간고사 나올 확률 높음- 함수 정의, 호출, 선언 함수 정의
   함수 만들기
   이름, 매개변수, 리턴형, 기능

 

void display(void) 

printf("안녕"); 

 함수 호출
   함수 사용하기
   이름, 매개변수
display();
 함수 선언( Prototype ,프로토 타입이라고도 한다)
   함수의 사용법
   이름, 매개변수, 리턴형
   컴파일러에게 함수에 대한 정보를 미리 줌
void display(void); 

 

멤버함수의 선언과 정의
 클래스 내에 나타난 함수의 프로토타입(prototype)은 함수를 선언하는 것
   int getAge();
 실제 함수를 사용하기 위해서는 멤버함수에 대한 정의가 필요
 멤버함수를 정의하는 2가지 방법
1. 클래스 안에서 정의
   클래스의 몸체가 비대해질 수 있으므로, 간단한 함수인 경우에 사용
2. 클래스 밖에서 정의
    클래스 안에서는 선언만 함 1번

class Dog{
private:
int age;
public:
int getAge() { //정의
return age;
}
void setAge(int a) { //정의
age=a;
}
};

 

2번

class Dog{
private:
int age;
public:
int getAge(); // 멤버함수 getAge선언
void setAge(int age); // 멤버함수 setAge선언
};
int Dog::getAge(){ // 멤버함수 getAge의 정의
return age;
}
void Dog::setAge(int a){ // 멤버함수 setAge의 정의
age=a;
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

시험 마지막 문제는 클래스 다이어 그램( 지난주 내용 참고)

 

Dog class 명
-age : int 변수
+ getAge()
+ setAge()
함수

- 는 private, +는 public

범위 지정 연산자(scope resolution operator) '::'
 멤버함수가 어느 클래스에 포함되어 있는지를 나타낼 때
 함수 안에서 전역변수를 접근할 때
#include <iostream>
using std::cout;
int a=3; //전역변수
int main()
{
int a=10; //지역변수
a=a+10; cout<<a<<","; //지역변수 a, 20
::a=::a+3;cout<<::a; //전역변수 a, 6
return 0;
}

변수 이름 앞에 ::를 두번 쓰게 되면 지역변수가 아닌 전역변수를 부르는 것

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

따로 정리한 내용

C++에서 변수 이름 앞에 ::를 두 번 쓰면 전역 변수를 참조하는 것
이는 범위 해결 연산자(scope resolution operator)를 사용하여 전역 네임스페이스에 있는 변수를 명시적으로 호출하는 방법
예를 들어:
cpp
int value = 10; // 전역 변수
void function() {
int value = 5; // 지역 변수
std::cout << value << std::endl; // 지역 변수 출력
std::cout << ::value << std::endl; // 전역 변수 출력
}
위 코드에서 ::value는 전역 변수를 가리키고, value는 지역 변수를 가리킵니다. 따라서 ::를 두 번 사용하는 것은 전역 변수를 부르는 것이 맞음

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

std namespace
 cin, cout 등 C++ 표준 라이브러리의 네임스페이스
 std::cin >> x;
 std::cout<< x;
 using std::cout;
   using std::cin;
   cin>>x;
   cout<< x;
 using namespace std;
cin>>x;
cout<<x;

#include <iostream>
using std::cout; //더 좋은 방법
using std::endl;
//이제부터 cout은 std::cout을 참조
int main()
{
cout<<"소프트웨어"<<endl;
return 0;
}



잘 쓰는 방법 2가지와↑

 

잘 안쓰는 방법1가지 ↓

#include <iostream>
using namespace std;
//네임스페이스로 std 사용,
//잘 쓰지 않음. 비추
int main()
{
cout<<"소프트웨어"<<endl;
return 0;
}

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

소스 파일 ppt.34
#include <iostream>
#include "aa.h"
#include "bb.h"
int add(int x, int y)
{
return x + y + 2;
}
int main()
{
std::cout << ::AA::add(1, 2); // aa에 있는 namespace의 add 함수 호출
std::cout << ::BB::add(1, 2); // bb에 있는 namespace의 add 함수 호출
std::cout << add(1, 2); // 전역에서 정의된 add 함수 호출
return 0;
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

해더 파일 aa.h

//aa.h
namespace AA
{
int add(int x, int y)
{
return x + y;
}
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

해더 파일 bb.h

//bb.h
namespace BB {
int add(int x, int y)
{
return x + y + 1;
}
}

이런식으로 적용

위의 namespace의 역할

 모든 식별자(변수, 함수 등의 이름)가 유일하도록 보장하는 코드 영역을 정의

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

using 지시문(directive) 
 using namespace std;
 std 네임스페이스의 모든 것을 사용하고 싶다.
 컴파일러가 인식하지 못하는 이름을 찾으면 std 네임스페이스를 검사
    컴파일러가 cout, cin 같이 네임스페이스를 알 수 없는 것을 만나면 std네임스페이스에서 찾음
 다른 라이브러리에서도 같은 이름의 함수나 변수가 있을 경우, 어떤 것을 사용할지 혼란스러울 수 있음
    큰 프로젝트나 여러 라이브러리를 사용할때는 using namespace std; 대신 std::를 추천

#include <iostream>
using namespace std;
int cout()
{
return 1;
}
int main()
{
cout << "Hello World!\n";
} //std::cout을 사용할지 cout()함수를 사용할지 모호함
//error: reference to 'cout' is ambiguous

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

정수 클래스 클래스 다이어 그램

Integer class 이름
-val::int 맴버 변수
+getVal()
+setVal()
맴버 함수

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

inline 함수의 장점

 함수를 호출하고 값을 반환하는데 드는 시간상의 지체(overhead)를 줄일 수있음

(왔다갔다 하지 않고 컴파일된 소스가 아예 붙어서 바로 실행되어서 빠른 실행이 가능하다)

 

단점

 inline 함수를 사용하면 프로그램의 전반적인 실행속도가 빨라지지만

  코드가 작은 함수일 때와 호출 빈도가 낮을 때 사용하는 것이 좋음
 아무리 작은 크기의 함수라도 여러 번 호출하게 되면 프로그램의 크기가 커져 실행 속도가 늦어지는 단점이 있음
 함수의 코드크기가 큰 경우에는 inline 함수로 선언했다 할지라도 컴파일러가 일반 함수로 취급할 수 있음
    Visual C++에서도 한/두 줄의 짧은 실행문을 갖는 함수를 inline 함수로 취급하고 그 이상의 함수는 컴파일러가 판단하여 처리함
 C++11부터는 컴파일러가 특정 조건을 만족하는 함수에 대해 자동으로 인라인 처리를 할 수 있음
   inline 키워드를 사용하지 않아도, 컴파일러가 성능을 고려하여 자동으로 인라인 함수로 만듦

=> 따라서 요새는 고민할 이유도 없고 크게 중요하진 않음

 

자동 inline 함수

 클래스 멤버함수의 정의 부분이 짧으면(코드가 작은 함수) 보통 클래스 선언부 내에서 함수를 정의
   이 경우 선언과 정의가 동시에 이루어짐
 멤버함수가 클래스 내부에서 정의되면 자동적으로 inline 함수가 됨(매우 중요한 특징)
 코드가 짧은 생성자와 소멸자(다음장 참조)가 대표적인 자동 inline 함수

class Dog{
private:
int age;
public:
int getAge() {return age;} // 멤버함수가 클래스 안에서 정의
void setAge(int a) {age=a;} // 자동으로 inline함수가 됨
};

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

객체의 멤버 호출
 직접참조연산자 : .
   일반 객체가 멤버(변수/함수)에 접근하기 위해 사용
 간접참조연산자 : ->
   포인터 객체가 멤버(변수/함수)에 접근하기 위해 사용
 happy.age (age가 private이므로 안됨)
 happy.getAge()       // 해피의 나이를 얻는다.
 happy.bark()           // 해피가 짖는다.
 pHappy->getAge() // pHappy의 나이를 얻는다.
 pHappy->bark()    // 포인터 객체 pHappy가 짖는다

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

실습3-2 오류 수정

#include <iostream>
using std::cout;
class Dog {
private:
int age; // 멤버 변수 선언
public:
int getAge(); // 멤버 함수 선언
void setAge(int a); // 멤버 함수 선언
};
// 멤버 함수 정의
int Dog::getAge() {
return age;
}
void Dog::setAge(int a) {
age = a;
}
int main() {
Dog happy; // Dog 클래스의 happy 객체 정의
happy.setAge(2); // Dog 클래스의 happy 객체의 age를 2로 설정
happy.setAge(3); // age는 private 멤버로 클래스 밖에서 접근 불가
cout << happy.getAge(); // age는 전용 멤버로 접근 불가
return 0;
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

지난 중간고사 문제

1. 사람 클래스를 선언하고 자신 객체를 정의하여 자신의 이름, 나이, 몸무게를 출력하는 프로그램
2. 멤버 함수는 두 가지 방법(클래스 내부, 클래스 외부)으로 각각 작성
힌트) kim.setAge(20);
cout<<kim.getAge();

3. 클래스 다이어그램 그리기

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

1번 중간 단게

#include <iostream>
class Man {
private:
int age;
double weight;
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
}
};
int main() {
Man jsy;
jsy.setAge(24);
std::cout << jsy.getAge();
return 0;
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
몸무게까지 하고 중간 포스트
#include <iostream>
class Man {
private:
int age;
double weight;
public:
int getAge() {
return age;
}
void setAge(int a) {
age = a;
}
double getWeight() { return weight; }
void setWeight(double w) { weight = w; }
};
int main() {
Man jsy;
jsy.setAge(24);
jsy.setWeight(70.2);
std::cout << "나이:" << jsy.getAge() << ", 몸무게:" << jsy.getWeight();
return 0;
 
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

#include <iostream>
class Man {
private:
int age;
double weight;
public:
int getAge() { return age; } // 자동 inline 함수
void setAge(int a) { age = a; } // 자동 inline 함수
double getWeight() { return weight; } // 자동 inline 함수
void setWeight(double w) { weight = w; } // 자동 inline 함수
void smile() { std::cout << "ㅎㅎㅎ\n"; } // 자동 inline 함수
//위의 5개는 자동inline 함수이다
};
int main() {
Man jsy;
jsy.setAge(24);
jsy.setWeight(70.2);
std::cout << "나이:" << jsy.getAge() << ", 몸무게:" << jsy.getWeight() << std::endl;
jsy.smile();
return 0;
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

위의 코드에서 자동inline 함수를 빼내서 자동inline 함수가 하나도 없도록 적용 시키는 코드로 변경 ↓
#include <iostream>
class Man {
private:
	int age;
	double weight;
public:
	int getAge();
	void setAge(int a);
	double getWeight();
	void setWeight(double w);
	void smile();

};
int Man:: getAge() { return age; }
void Man::setAge(int a) { age = a; }
double Man:: getWeight() { return weight; }
void Man:: setWeight(double w) { weight = w; }
void Man:: smile() { std::cout << "ㅎㅎㅎ\n"; }

int main() {
	Man jsy;
	jsy.setAge(24);
	jsy.setWeight(70.2);
	std::cout << "나이:" << jsy.getAge() << ", 몸무게:" << jsy.getWeight() << std::endl;
	jsy.smile();
	return 0;
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#include <iostream>
class Man {
private:
	int age;
	double weight;
public:
	int getAge();
	void setAge(int a);
	double getWeight();
	void setWeight(double w);
	void smile();
	void endOfYear() {age = age + 1;}
};
int Man:: getAge() { return age; }
void Man::setAge(int a) { age = a; }
double Man:: getWeight() { return weight; }
void Man:: setWeight(double w) { weight = w; }
void Man:: smile() { std::cout << "ㅎㅎㅎ\n"; }

int main() {
	Man jsy;
	jsy.setAge(24);
	jsy.setWeight(70.2);
	jsy.smile();
	std::cout << "나이:" << jsy.getAge() << ", 몸무게:" << jsy.getWeight() << std::endl << '\n';
	jsy.smile();
	jsy.endOfYear();
	std::cout << "나이:" << jsy.getAge() << ", 몸무게:" << jsy.getWeight() << std::endl << '\n';
	return 0;
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

3번 위의 코드로 클래스 다이어 그램 그리기

Man class 명
-age:int
-weight:double
맴버 변수
+getAge()
+setAge()
+getweight()
+setweight()
+smile()
+endOfYear()
맴버 함수

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

https://pythontutor.com/render.html#mode=display 실행 되는 순서를 알 수 있도록 하는 사이트