C++(7)

송예원·2024년 7월 30일

c++

목록 보기
7/12
  1. 객체지향 설계 원칙
    • SOLID원칙: 소프트웨어의 유지/ 보수와 확장성에 도움이 되는 다섯가지 기본 원칙

1) 단일 책임 원칙 (SRP)

  • 클래스는 한 가지 기능만 수행해야 하고, 한 가지 이유로만 변경해야 한다
    = 클래스를 설계할 때 역할을 복잡하지 않게 해야한다

2) 개방/ 폐쇄 원칙 (OCP)

  • 확장에 개방, 수정에 폐쇄
    = 동적 바인딩 이용시 프로그램은 새로운 기능을 추가할 수 있는 방법 (확장에 개방)이 생기고, 다른 코드에 파급 효과가 없어 추가되는 기능 외에는 수정이 필요 없음 (수정에 폐쇄)
  • 추상클래스 (인터페이스) 이용해 구현 가능
  • 템플릿 메서드 패턴: 프로그램에서 주요 기능의 흐름은 추상클래스를 이용해 작성하고 이를 상속받아 구현하는 클래스에 따라서 세부동작이 결정되게하는 것
  • 소프트웨어 개발과 유지/ 보수에 있어 아주 중요

3) 리스코프 치환 원칙 (LSP)

  • 하위클래스는 상위클래스를 대체할 수 있어야 한다
    => 다형성의 동작원리 설명
  • is-a 관계로 정의된 클래스는 LSP따르는 클래스...
    = 부모클래스를 상속받아 구현한 자식클래스는 부모클래스로 업캐스팅 가능
    = 자식클래스에서 부모클래스의 멤버함수를 상속받아 오버라이딩하거나 유지해야함

4) 인터페이스 분리원칙 (ISP)

  • 단일책임원칙을 인터페이스에 적용한 것
    = 인터페이스는 작고 섬세해야하며, 클래스는 필요한 인터페이스 까지만 구현해야한다

5) 의존성 역전 원칙 (DIP)

  • 상위 수준 모듈은 하위 수준의 모듈에 의존해서는 안되며 상위/ 하위 수준 모두 추상레이어 (인터페이스)에 의존해야한다
    = 구체적인 것보다는 추상적인 것에 의존해야한다, 추상클래스와 인터페이스를 사용해 준수
    (개방/ 폐쇄 원칙을 적용하기 위해 사용=> 의존성 역전 원칙 적용시 함께 적용)
  1. 템플릿

1) 함수 템플릿

  • 템플릿: 함수 하나로 다양한 형식의 데이터를 같은 알고리즘으로 처리할 수 있게 도와줌
  • 템플릿 사용시 매개변수의 데이터 형식을 함수를 작성하는 시점이 아닌 사용하는 시점에 정할 수 있음= 함수 템플릿이 포함된 소스코드를 컴파일하면 해당 함수에 사용된 데이터 형식으로 함수의 실제 구현체가 만들어짐
#include <iostream>
#include <string>
using namespace std;
template <typename T> //템플릿 선언
T data_sum (T operand1, T operade2) {// 함수템플릿 정의
	return operade1 + operade2;
}
int main () {
	int data1=3, data2=5;
    double data3= 4.5, data4= 8.9
    string data5= "Hello,", data6= "World!";
    cout<<data_sum(data1, data2)<<endl;
	cout<<data_sum(data3, data4)<<endl;
	cout<<data_sum(data5, data6)<<endl;
    return 0;
}
8
13.4
Hello, World!
<typename 매개변수,, >= 임의의 데이터형식= 템플릿 매개변수
=> 여러개 선언하려면 typename과 함께 나열
  • 템플릿의 선언 방법이나 분문 정의방법은 일반 함수와 같지만함수에 전달할 인자의 데이터 형식을 고정하지 않아도 된다는 특징이 존재
  • 한 번 정의해놓으면 다양한 데이터형식을 처리할 수 있지만, 그렇기 때문에 모든 데이터 형식에 대응할 수 있는 알고리즘으로 정의되어야 함
  • 템플릿의 인스턴스화: 컴파일러가 함수템플릿을 호출하는 구문을 만나고, 인자로 전달한 값으로 템플릿 매개변수의 데이터 형식을 추론하여 이 형식으로 완성된 함수를 오브젝트 코드로 만드는 과정
  • 함수템플릿은 컴파일시점에 데이터 형식별로 템플릿이 인스턴스로 만들어지므로 템플릿을 많이 사용하면 컴파일 시간이 길어짐
  • 데이터 형식 추론과 명시적 호출
  • 데이터 형식이 명확하지 않으면 추론이 불가능해 컴파일 오류 발생 가능
    (ex) 자료형이 맞지 않는 경우)
    => 필요할 경우 명시적 형변환을 해야함
  • 명시적 형변환: 함수템플릿 호출문에서 인자를 입력하기 전 <>로 데이터 형식을 명시 => 컴파일러가 데이터 형식을 추론하지 않고 해당 형식으로 변환한 후에 바로 인스턴스화
    (ex) char형과 string)
  • 템플릿 특수화: 특수한 상황일 때만 별도의 함수 템플릿으로 만들어 처리하는 방법 => 특정 데이터 형식만 다른 알고리즘으로 처리하게 만들기 가능
    = 목적이 같은 알고리즘을 처리 방법만 다르게 표현

  • 명시적 특수화: 모든 템플릿 매개변수를 특정 데이터 형식으로 지정
  • 부분 특수화: 일부 템플릿 매개변수만 특정 데이터 형식으로 지정
  • 함수 템플릿에서는 명시적 특수화만 사용 가능
    => 템플릿 매개변수를 사용하지 않고 함수에 데이터 형식을 모두 지정
    함수이름과 매개변수 개수는 변경하지 않음
#include <iostream>
#include <string>
using namespace std;
template <typename T> //템플릿 선언
T data_sum (T operand1, T operade2) {// 함수템플릿 정의
	return operade1 + operade2;
}
template<>
double data_sum (double operand1, double operand2) {
    return (int)operand1 + (int)operand2;
}
int main () {
	int data1=3, data2=5;
    double data3= 4.5, data4= 8.9
    string data5= "Hello,", data6= "World!";
    cout<<data_sum(data1, data2)<<endl;
	cout<<data_sum(data3, data4)<<endl;
	cout<<data_sum(data5, data6)<<endl;
    return 0;
}
8
12
Hello, World!
  • 템플릿 특수화를 사용하지 않고 함수를 따로 만들어도 됨!
    (그래도 템플릿을 사용하는 소스코드에서 특정 데이터만 다르게 처리해야 할 때는 템플릿 특수화를 이용하는 것이 더 좋음)

2) 클래스 템플릿

  • 클래스 템플릿: 템플릿을 클래스에 적용시킨 것
    템플릿 매개변수를 활용해 다양한 형식에 대응할 수 있는 범용 클래스를 만드는 방법
    클래스 템플릿을 직접 선언하기 보다는 이미 선언된 클래스 템플릿을 이용하는 경우가 더 많음
template <typename Type1, typename Type2>
class data_package {
	public:
    	data_package (Type1 first, Type2 second) : first(first), second(second){}
    private:
    Type1 first
    Type2 second;
};

일반 클래스와 비슷하지만, 범용 데이터 형식을 지정할 자리에 템플릿 매개변수를 사용한다는 특징이 있음

  • 템플릿 매개변수는 멤버함수, 멤버변수에 모두 사용/ 함수 템플릿을 만든 것 처럼 멤버함수를 만들면 됨
  • 부분 특수화 사용 가능
  • 클래스 템플릿으로 객체 생성시 템플릿 매개변수에 사용할 데이터 형식 지정 -> 생성자나 멤버함수에서 템플릿 매개변수에 맞춰 지정한 데이터 형식을 일관되게 유지하며 사용 -> 컴파일러가 지정된 데이터 형식을 사용하는 클래스를 인스턴스화
int main() {
	data_package<int, double> template_inst1(5, 10.5);
    data_package<string, int> template_inst2("문자열",10);
...

+) C++표준 라이브러리 함수들은 다양한 데이터 형식을 받아서 같은 알고리즘으로 동작하는 클래스 템플릿으로 구성
+) 클래스는 이미 기능을 묶어서 추상화된 범용성을 가지고 있지만, 기능을 추상화해서 표현해도 데이터 형식은 고정해 사용함,,, -> 템플릿 사용해서 데이터 형식까지 범용적으로 만들 수 있음

  • 클래스 템플릿에서 형식 추론
  • 함수템플릿에서는 컴파일러가 템플릿 매개변수의 데이터 형식을 추론할 수 있지만 클래스 템플릿에서는 객체를 생성할 때 템플릿 매개변수의 형식을 명시해주어야 함 =>> 데이터 형식이 명확하지 않다면 직접 명시해주는 것이 오류를 막는 것에 도움
  • 부분특수화: 클래스 템플릿을 인스턴스화할 때 매개변수를 특정 형식의 값으로 처리하는 것
template <typename T>
class data_package <string, T>{
	public:
    	data_package (string first, T second) : first(first), second(second){}

템플릿 객체 생성시 첫번째 인자의 타입을 string으로 하면 부분 특수화가 적용된 class data_package<string, T>가 인스턴스화 됨 => 형식을 특정하여 별도로 처리 가능


+) 클래스 템플릿은 일반 클래스와 거의 모든 동작이 같음,,, 하지만 클래스 템플릿의 선언과 정의를 별도의 파일로 분리하면 안됨 (클래스 템플릿은 선언과 정의가 같이 있어야 함)

  • 중첩 클래스 템플릿: 클래스 템플릿 중첩 가능
  • 안쪽 클래스를 멤버변수처럼 사용: 멤버변수이므로 바깥쪽 클래스에서 안쪽 클래스의 멤버변수를 선언하고 필요하면 초기화도 진행
  • 안쪽 클래스를 독립된 객체로 선언해서 사용: 템플릿이 중첩되어 있기 때문에 바깥쪽 클래스의 템플릿 매개변수도 모두 입력해야함
  • 템플릿 매개변수 기본값: 매개변수의 기본값 정의해놓으면 함수를 호출할 때 값을 전달하지 않아도 됨+ 템플릿 매개변수도 기본값 정할 수 있음 (기본값= 데이터 형식)
  • 클래스 템플릿의 객체를 생성할 때 템플릿 매개변수의 형식을 입력하지 않아도 기본으로 설정한 데이터 형식이 지정됨
  • 클래스 템플릿 프렌드
  • 클래스 템플릿도 프렌드 클래스와 함수를 가질 수 있음 (단, 인스턴스화 순서와 프렌드 규칙을 준수해야하므로 주의,,)
    +) 프렌드 클래스는 friend로 지정되기 전 선언과 정의가 있어야 함


    +) 특정 형식만 수용하는 템플릿
template <typename C>
void printout_friend_element (data_package<C> &data_object)

- 템플릿이나 클래스 템플릿에서 사용한 템플릿 매개변수는 소스코드를 작성할 때가 아니라 컴파일할 때 추론된 형식으로 인스턴스화 된다. - 템플릿 매개변수로 정의한 함수나 클래스의 멤버함수는 전체 매개변수의 데이터 형식을 지정하는 명시적 특수화와 일부 매개변수의 데이터 형식을 지정하는 부분 특수화가 있고, 부분 특수화는 클래스 템플릿에서만/ 명시적 특수화는 함수템플릿과 클래스 템플릿 모두에서 사용 가능

0개의 댓글