# C++ 키워드

niraaah·2023년 5월 2일
2

WHO 스터디

목록 보기
2/2
post-thumbnail

1. Lambda


: 익명 함수를 정의할 수 있는 기능.

  • 형식 : 개시자 + 인자 + 반환 타입 + 함수의 몸통
  • 다른 함수나 객체의 인자로 전달되거나 반환되는 함수 객체를 생성하는 데 사용.
  • 함수 객체로 구현할 경우 번거롭게 구조체를 먼저 정의해서 사용할 필요가 없기 때문에 간단하게 표현이 가능하다.
// 개시자 없음, 인자 없음, 리턴 타입 없음.
#include <iostream>
int main() {
    []() { std::cout << "Hello lambda!" << std::endl; }();
    return 0;
}
-
// 개시자 없음, 리턴 타입 없음.
#include <iostream>
int main() {
    [](std::string name) {
        std::cout << "My name is " << name << std::endl;
    }("Dangdang");
    return 0;
}
-
// std::function에 대입 가능.
#include <iostream>
#include <functional>
int main() {
    // std::function<void (std::string)>
    auto introduce = [](std::string name) {
        std::cout << "My name is " << name << std::endl;
    };
    introduce("Jinsoo Heo");
    return 0;
}

2. Predicate >> 몰루입니다ㅠ

: 조건자. true/false 또는 int를 리턴하는 함수.

3. Array vs Pointer

  • array의 배열 변수가 보유한 주소는 배열의 첫번째 요소의 주소.
  • arr = 배열의 시작 원소를 가리킴
  • &arr = 배열 자체를 가리키는 포인터
	#include <iostream>
	using namespace std;
	void foo(int* arr){
		cout << sizeof(arr);
	}
	int main(){
		int arr[3] = { 1, 2, 3 };
	    cout << sizeof(arr);
		foo(arr);
 	   return 0;
	}
	[출력 결과]: 12 4

4. Pointer vs Reference

: 이미 정리함

5. Smart Pointer

: 포인터처럼 동작하는 클래스 템플릿. new 키워드가 반환하는 주소값을 대입하면, 따로 메모리를 해제할 필요가 없음. (사용이 끝난 메모리를 자동으로 해제해줌!)

a. unique_ptr : 하나의 스마트 포인터만이 특정 객체를 소유할 수 있도록, 객체에 소유권 개념을 도입한 스마트 포인터.

  • 해당 객체의 소유권을 가지고 있을 때만, 소멸자가 해당 객체를 삭제할 수 있음.
  • move() 멤버 함수를 통해 소유권을 이전할 수는 있지만, 복사할 수는 없음.
  • 소유권이 이전되면, 이전 unique_ptr 인스턴스는 더는 해당 객체를 소유하지 않게 재설정됨.
    unique_ptr<int> ptr01(new int(5));
    // int형 unique_ptr 선언
    auto ptr02 = move(ptr01);
    // ptr01에서 ptr02로 소유권 이전
    ptr02.reset();	
    // ptr02가 가리키고 있는 메모리 영역을 삭제
    ptr01.reset();	
    // ptr01가 가리키고 있는 메모리 영역을 삭제

b. shared_ptr : 하나의 특정 객체를 참조하는 스마트 포인터가 총 몇 개인지를 참조하는 스마트 포인터.

  • 참조 횟수는 특정 객체에 새로운 shared_ptr이 추가될 때마다 1씩 증가하며, 수명이 다할 때마다 1씩 감소함.
  • use_count() : shared_ptr 객체가 현재 가리키고 있는 리소스를 참조 중인 소유자의 수를 반환
  • make_shared(): shared_ptr 인스턴스를 안전하게 생성
	shared_ptr<Person> a = make_shared<Person>("A", 30);
	cout << a.use_count() << endl;
	auto b = a;
	cout << a.use_count() << endl
	b.reset(); // shared_ptr인 b를 해제함.
	cout << a.use_count() << endl; 
	[출력 결과]
	1
	2
	1

c. weak_ptr: 하나 이상의 shared_ptr 인스턴스가 소유하는 객체에 대한 접근을 제공하지만, 소유자의 수에는 포함되지 않는 스마트 포인터.

  • 서로 상대방을 가리키는 shared_ptr 인스턴스 사이의 순환 참조를 제거하기 위해 사용.

6. lvalue vs rvalue

a. lvalue : 단일 표현식 이후에도 사라지지않고 지속되는 객체.
b. rvalue : 표현식이 종료된이후에는 더이상 존재하지 않는 임시적인 값.

	[예시]
    a = b + c; 에서
    "a"는 lvalue, "b + c"는 rvalue

7. Char vs std::string

a. char : 문자. ASCII 코드로 해석되는 1byte의 정수.
b. std::string : ""를 이용해 표현되는 문자열 상수.
(이름을 가지고 있지 않으며 문자열의 내용 또한 변경할 수 없기 때문.)

8. Literal constant

: '상수'. 코드에 직접 삽입된 값. 변경할 수 없음.

  • 숫자 리터럴에서는 유형을 결정하는 접미사가 포함될 수 있고 선택사항으로 생략하면 컴파일러는 의도하는 것이 어떤 종류의 상수인지 유추함.
  • 문자와 문자열 리터럴도 있음.

9. Function Overloading

: 다른 매개 변수를 가진 같은 이름의 여러 함수를 만듦.

	void Display(const char* str, int n){
    	for (int i = 0; i < n; i++){
        	printf(str);
        }
    }
    void Display(const char* str1, const char* str2){
    	printf(str1 + str2);
    }
    void Display(int x, int y){
    	printf(x * y);
    }
    void Display(double x, double y){
    	printf(x / y);
    }
    // 여기서 Display(4.2, 3); 을 하면
    // 함수가 두개 호출 가능해 컴파일 오류 발생.

10. Operator Overloading

: 기존에 제공하고 있는 연산자를 전역 함수 또는 클래스로 재정의하여 사용자 정의해 사용하는 것.

  • 새로운 연산자를 정의할 수 없음.
  • 기본 제공 데이터 형식에 적용할 때 연산자의 의미를 다시 정의할 수 없음.
  • 오버로드 된 연산자는 non-static 클래스 멤버 함수거나 전역 함수여야 함.
  • 단항 연산자 또는 이항 연산자(&, *, +, -)로 오버로드 가능하며 각 사용을 별도로 오버로드 할 수 있음.
  • 멤버함수로 오버로드된 연산자의 첫번째 파라미터는 항상 연산자가 호출되는 객체의 클래스 형식.
  • 오버로드 할 수 없는 연산자: . .* :: ?: # ##
	#include <iostream>
    using namespace std;
    class Point{
    private:
    	int x, y;
    public:
    	Point(int x_, int y_){
        	x = x_;
            y = y_;
        }
        void print(){
        	cout << "x : " << x << ", y : " << y << "\n";
        }
        Point operator + (Point& p){
        	x = x + p.x;
            y = y + p.y;
            return Point(x, y);
        }
    };
    
    int main(){
    	Point p1 = { 1, 1 };
        Point p2(2, 2);
        
        Point p3 = p1 + p2;
        
        p3.print();
        return 0;
    }
    
	[출력 결과]
	x: 3, y: 3

11. Constructor, Copy constructor

a. 생성자 : 해당 클래스의 객체가 인스턴스화될 때 자동으로 호출되는 특수한 종류의 멤버 함수.

  • 일반적으로 클래스의 멤버 변수를 적절한 기본값 또는 사용자 제공 값으로 초기화하거나 클래스를 사용하는 데 필요한 설정(ex. 파일 열기 등)이 필요한 경우 사용.
  • 생성자 이름은 클래스와 이름이 같아야함.
  • 생성자는 리턴타입이 없다. (void도 X)

b. 복사 생성자 : 객체의 복사본을 생성할 때 호출되는 생성자.

  • 자신과 같은 클래스 타입의 다른 객체에 대한 참조를 인수로 전달받아, 그 참조를 가지고 자신을 초기화 하는 방법.
  • 새롭게 생성되는 객체가 원본 객체와 같으면서도 완전한 독립성을 갖게 함. (복사 생성자를 이용한 대입은 깊은복사이기 때문!)
    c. 복사 대입 연산자 : 같은 타입의 객체를 이미 생성되어 이쓴 객체에 값을 복사할 때 사용.
  • 객체가 함수에 인수로 전달될 때
  • 함수가 객체를 반환값으로 반환할 때
  • 새로운 객체를 같은 클래스 타입의 기존 객체와 똑같이 초기화 할 때
		#include <iostream>

	using namespace std;

	class Person{
	public:
    	int age;
    	char* name;
 	   Person(int _age, const char* _name){
    	    age = _age;
        	name = new char[strlen(_name) + 1];
        	strcpy(name, _name);
    	}
    
      Person(const Person& p){ //복사 생성자로 깊은 복사하기
      	 	age = p.age;
        	name = new char[strlen(p.name) + 1];
       		strcpy(name, p.name);
  	  }
    
    	void infoPerson(){
        	cout << "이름: " << name << endl;
        	cout << "나이: " << age << endl;
    	}
	};

	void main(){
    	Person A(20, "홍길동");
    	Person B = A;
    
   		B.age = 30;
    	strcpy(B.name, "이순신");
    
    	A.infoPerson();
    	B.infoPerson();
	}
	[출력 결과]
	이름: 홍길동
	나이: 20
	이름: 이순신
	나이: 30

참고: 얕은 복사 & 깊은 복사

12. Abstract class

a. 순수 가상 함수 : 파생 클래스에서 재정의할 것으로 기대하는, '반드시 재정의 되어야만 하는' 멤버 함수.

  • 형식: virtual 멤버함수원형 = 0;
	예시: virtual void foo() = 0;

b. 추상 클래스 : 하나 이상의 순수 가상 함수를 포함하는 클래스.

  • 반드시 사용되어야 하는 멤버 함수를 추상 클래스에 순수 가상 함수로 선언해 놓으면, 이 클래스로부터 파생된 모든 클래스에서는 이 가상 함수를 반드시 재정의해야 함.
  • 동작이 정의되지 않은 순수 가상 함수를 포함하고 있으므로, 인스턴스 생성 X.
	class Animal{
    public:
    	virtual ~Animal(){}		// 가상 소멸자 선언
        virtual void Cry() = 0;	//순수 가상 함수 선언
    class Dog : public Animal{
    public:
    	virtual void Cry(){ cout << "멍멍!" << endl; }
    }
    class Cat : public Animal{
    public:
    	virtual void Cry(){ cout << "야옹!" << endl; }
    }
    int main(){
    	Dog myDog;
        myDog.Cry();
        Cat myCat;
        myCat.Cry();
        return 0;
    }
    [출력 결과]
    멍멍!
    야옹!
    /*
    Animal 클래스를 상속받는 파생 클래스인
    Dog 클래스와 Cat 클래스는
    Cry() 함수를 오버라이딩해야만
    인스턴스를 생성할 수 있음
    */

13. Inheritance

: 상속.

	[형식]
    class 자식클래스이름 : 접근제한자 부모클래스이름 {...}

a. private 상속

	#include <iostream>
	using namespace std;

	class A {
	private:
		int a;
	protected:
		int b;
	public:
		int c;
	};

	class B : private A { 
    //b,c맴버 변수는 private 맴버로 접근 범위 졻혀짐
	};


	int main() {
		B b;
    	//a = private, b = private, c = private
		b.a;
		b.b;
		b.c;
	}

b. protected 상속

	#include <iostream>
	using namespace std;

	class A {
	private:
		int a;
	protected:
		int b;
	public:
		int c;
	};

	class B : protected A { 
	//c맴버 변수는 protected 맴버로 접근 범위 졻혀짐
	};


	int main() {
		B b;
		//a = private, b = protected, c = protected
		b.a;
		b.b;
		b.c;
	}

c. public 상속

	#include <iostream>
	using namespace std;

	class A {
	private:
		int a;
	protected:
		int b;
	public:
		int c;
	};

	class B : public A {
	//맴버 변수의 접근 제한에 변화없음
	};


	int main() {
		B b;
		//a = private, b = protected, c = public
		b.a;
		b.b;
		b.c;
	}

14. virtual function

: 가상함수를 선언할 때 사용하는 키워드.

	[형식]
    virtual 반환형 함수이름();
  • 가상함수로 선언하면 동적 바인딩이 되어서 포인터의 타입이 아닌 포인터가 가리키는 객체의 타입에 따라 멤버 함수를 선택하게 됨.
  • 클래스의 public 섹션에 선언.
  • static 또는 friend 불가.
  • 기본 클래스의 포인터 또는 참조를 통해 access 해야함.
  • 반환형과 매개변수는 기본 클래스와 파생 클래스에서 동일.
  • override 시에는 virtual 키워드를 붙여도 되고 안붙여도 됨.
  • 가상 소멸자를 가질 수 있지만 가상 생성자를 가질 수 없음.

15. override

: 상속받았을 때 부모 클래스의 함수를 사용하지 않고 다른 기능을 사용할 때 함수를 자식 클래스에서 같은 이름, 같은 매개변수로 재정의해서 사용하는 것.
cf) 오버로딩: 함수 중복 정의- 같은 이름의 함수에 매개변수를 다르게 사용해 매개변수에 따라 다른 함수가 실행되는 것.

  • 오버라이드 하고자 하는 메소드가 상위 클래스에 존재해야 함.
  • 메소드 이름이 같아야함.
  • 파라미터 개수와 자료형이 같아야함.
  • 리턴형이 같아야함.
  • 상위 메소드와 동일하거나 내용이 추가 되어야 함.

16. Polymorphism

: 다형성(여러가지 형태를 갖는 성질).

  • 함수의 기능적 다형성과 상속에 의해 만들어진 계층 관계를 활용하는 기술
  • 상속구조를 가지고 있는 경우 상위 클래스의 포인터나 참조자로 하위 클래스의 기능과 자료를 사용할 수 있다.
  • 상위 클래스에 가상 멤버 변수가 하나 이상 있어야함.
  • 하위 클래스에서 오버라이딩 할 멤버 함수가 없다면 상위 클래스의 소멸자를 가상함수로 만들고 객체는 상위 클래스의 포인터나 참조자로 만들어야함.
    a. 가상 함수 : 부모 클래스와 자식 클래스에 동일한 이름의 함수의 다른 작동
    b. 함수 템플릿 : 동일한 이름의 함수가 다양한 자료형을 처리
    c. 함수 오버로드 : 동일한 이름의 함수가 다른 작동
    d. 연산자 오버로드 : 한가지 연산자가 다양한 작동

17. up-casting, down-casting

a. up-casting : 파생 클래스의 객체를 기본 클래스의 포인터로 가리키는 것.

	예시:
    	Pizza cheesePizza;
    	Pizza* pp = &cheesePizza;
    	Circle cc = pp;	// 업캐스팅

b. down-casting : 기본 클래스 포인터가 가리키는 객체를 파생 클래스의 포인터로 가리키는 것. 업캐스팅에서 다시 원래 형으로 되돌려주는 작업. 업캐스팅과 달리 '명시적 타입 변환'을 지정해야 함.

	예시:
    	pp = (Pizza*) cc;

18. Template

	[형식]
    template <typename 이름>
  • 컴파일러가 인자값으로 들어가는 자료형을 보고 타입을 유추하여 유연하게 함수에 적용
    a. Class Template
	#include <iostream>
	using namespace std;
	template <typename T>

	T add(T x, T y) {
	    return x + y;
	}
	int main()
	{
	    int num1 = 10, num2 = 20;
	    cout << add(num1, num2) << endl;
    
	    double num3 = 10.52, num4 = 20.24;
	    cout << add(num3, num4) << endl;
    
	    return 0;
	}

b. Function Template

	#include <iostream>
	using namespace std;
	template <class T>
	//template <typename T> 와 같은 표현
	class Calcu
	{
	private:
	    T num1;
	    T num2;
	public:
	    Calcu(T num1, T num2) {
	        this->num1 = num1;
	        this->num2 = num2;
	    }
	    T GetAdd() {
	        return num1 + num2;
	    }
	};
	int main()
	{
	    Calcu<int> calcu1(10, 20);
	    cout << calcu1.GetAdd() << endl;
    
	    Calcu<double> calcu2(10.52, 20.24);
	    cout << calcu2.GetAdd() << endl;
	}

c. variadic functions : 가변 길이 템플릿

	#include <iostream>

	template <typename T>
	void print(T arg) {
	  std::cout << arg << std::endl;
	}

	template <typename T, typename... Types>
	void print(T arg, Types... args) {
	  std::cout << arg << ", ";
	  print(args...);
	}

	int main() {
	  print(1, 3.1, "abc");
	  print(1, 2, 3, 4, 5, 6, 7);
	}

19. Exception

a. try-catch / throw
>> JAVA로 정리했었다!
b. std::exception

	#include <exception> 해야함
  • logic_error
    invalid_argument
    domain_error
    length_error
    out_of_range
    future_error(C++11)
  • runtime_error
    range_error
    overflow_error
    underflow_error
    regex_error(C++11)
    system_error(C++11)
    ios_base::failure(C++11)
  • bad_typeid
  • bad_weak_ptr(C++11)
  • bad_function_call(C++11)
  • bad_alloc
    bad_array_new_length(C++11)
  • bad_exception
  • ios_base::failure(until C++11)

[출처]

람다 - 모두코드
람다 - devkoriel
조건자 - Maple story
배열과 포인터 - 소년코딩
배열과 포인터 - kangworld
스마트 포인터 - TCP school
Lvalue & Rvalue - 별이 빛나는 세상
문자 - 소년코딩
문자열 - 달려라 승이
리터럴 - 소년코딩
함수 오버로딩 - TCP school
연산자 오버로딩 - 열코
생성자 - 소년코딩
복사 생성자 - TCP school
복사 생성자 - 코딩 팩토리
추상 클래스 - TCP school
추상 클래스 - HwanShell
상속 - 끝나지 않는 프로그래밍 일기
상속 - reakwon
가상 클래스 - 열코
가상 클래스 - 코딩 팩토리
오버라이드 - Insert Brain Here
다형성 - C++이야기
다형성 - 꽈이의 게임개발
lesslate
템플릿 - 코딩 팩토리
가변 길이 템플릿 - 모두의 코드
exception - 평생 공부
exception - C++ 이야기

profile
코딩천재

0개의 댓글

관련 채용 정보